diff --git a/package-lock.json b/package-lock.json index ce08dbd33d..b51ca8de3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,26 +1,27 @@ { "name": "concerto", - "version": "0.82.10", + "version": "0.82.11", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.0.0" } }, "@babel/generator": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", - "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.4.tgz", + "integrity": "sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w==", "dev": true, "requires": { - "@babel/types": "^7.11.5", + "@babel/types": "^7.6.3", "jsesc": "^2.5.1", + "lodash": "^4.17.13", "source-map": "^0.5.0" }, "dependencies": { @@ -33,48 +34,42 @@ } }, "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" } }, "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/types": "^7.10.4" + "@babel/types": "^7.0.0" } }, "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", "dev": true, "requires": { - "@babel/types": "^7.11.0" + "@babel/types": "^7.4.4" } }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", + "esutils": "^2.0.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -116,37 +111,37 @@ } }, "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.4.tgz", + "integrity": "sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==", "dev": true }, "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" } }, "@babel/traverse": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", - "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.3.tgz", + "integrity": "sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.5", - "@babel/types": "^7.11.5", + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.6.3", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.6.3", + "@babel/types": "^7.6.3", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.19" + "lodash": "^4.17.13" }, "dependencies": { "globals": { @@ -158,13 +153,13 @@ } }, "@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz", + "integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", + "esutils": "^2.0.2", + "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" }, "dependencies": { @@ -389,6 +384,37 @@ "chalk": "^2.3.1", "execa": "^1.0.0", "strong-log-transformer": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@lerna/clean": { @@ -425,12 +451,75 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -457,10 +546,21 @@ "ansi-regex": "^4.1.0" } }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", "dev": true }, "yargs": { @@ -494,6 +594,37 @@ "chalk": "^2.3.1", "figgy-pudding": "^3.5.1", "npmlog": "^4.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@lerna/collect-updates": { @@ -580,6 +711,12 @@ "whatwg-url": "^7.0.0" }, "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -802,6 +939,37 @@ "@lerna/query-graph": "3.18.5", "chalk": "^2.3.1", "columnify": "^1.5.4" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@lerna/log-packed": { @@ -1045,6 +1213,12 @@ "json-parse-better-errors": "^1.0.1" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -1259,6 +1433,26 @@ "write-json-file": "^3.2.0" }, "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, "load-json-file": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", @@ -1293,6 +1487,15 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -1323,21 +1526,21 @@ "dev": true }, "@octokit/auth-token": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.2.tgz", - "integrity": "sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.4.tgz", + "integrity": "sha512-LNfGu3Ro9uFAYh10MUZVaT7X2CnNm2C8IDQmabx+3DygYIQjs9FwzFAHN/0t6mu5HEPhxcb1XOuxdpY82vCg2Q==", "dev": true, "requires": { - "@octokit/types": "^5.0.0" + "@octokit/types": "^6.0.0" } }, "@octokit/endpoint": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.6.tgz", - "integrity": "sha512-7Cc8olaCoL/mtquB7j/HTbPM+sY6Ebr4k2X2y4JoXpVKQ7r5xB4iGQE0IoO58wIPsUk4AzoT65AMEpymSbWTgQ==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.10.tgz", + "integrity": "sha512-9+Xef8nT7OKZglfkOMm7IL6VwxXUQyR7DUSU0LH/F7VNqs8vyd7es5pTfz9E7DwUIx7R3pGscxu1EBhYljyu7Q==", "dev": true, "requires": { - "@octokit/types": "^5.0.0", + "@octokit/types": "^6.0.0", "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, @@ -1356,6 +1559,12 @@ } } }, + "@octokit/openapi-types": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-2.0.1.tgz", + "integrity": "sha512-9AuC04PUnZrjoLiw3uPtwGh9FE4Q3rTqs51oNlQ0rkwgE8ftYsOC+lsrQyvCvWm85smBbSc0FNRKKumvGyb44Q==", + "dev": true + }, "@octokit/plugin-enterprise-rest": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", @@ -1383,9 +1592,9 @@ } }, "@octokit/plugin-request-log": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz", - "integrity": "sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.2.tgz", + "integrity": "sha512-oTJSNAmBqyDR41uSMunLQKMX0jmEXbwD1fpz8FG27lScV3RhtGfBa1/BBLym+PxcC16IBlF7KH9vP1BUYxA+Eg==", "dev": true }, "@octokit/plugin-rest-endpoint-methods": { @@ -1410,14 +1619,14 @@ } }, "@octokit/request": { - "version": "5.4.9", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.9.tgz", - "integrity": "sha512-CzwVvRyimIM1h2n9pLVYfTDmX9m+KHSgCpqPsY8F1NdEK8IaWqXhSBXsdjOBFZSpEcxNEeg4p0UO9cQ8EnOCLA==", + "version": "5.4.12", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.12.tgz", + "integrity": "sha512-MvWYdxengUWTGFpfpefBBpVmmEYfkwMoxonIB3sUGp5rhdgwjXL1ejo6JbgzG/QD9B/NYt/9cJX1pxXeSIUCkg==", "dev": true, "requires": { "@octokit/endpoint": "^6.0.1", "@octokit/request-error": "^2.0.0", - "@octokit/types": "^5.0.0", + "@octokit/types": "^6.0.3", "deprecation": "^2.0.0", "is-plain-object": "^5.0.0", "node-fetch": "^2.6.1", @@ -1426,12 +1635,12 @@ }, "dependencies": { "@octokit/request-error": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.2.tgz", - "integrity": "sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.4.tgz", + "integrity": "sha512-LjkSiTbsxIErBiRh5wSZvpZqT4t0/c9+4dOe0PII+6jXR+oj/h66s7E4a/MghV7iT8W9ffoQ5Skoxzs96+gBPA==", "dev": true, "requires": { - "@octokit/types": "^5.0.1", + "@octokit/types": "^6.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" } @@ -1497,18 +1706,19 @@ } }, "@octokit/types": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz", - "integrity": "sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.1.2.tgz", + "integrity": "sha512-LPCpcLbcky7fWfHCTuc7tMiSHFpFlrThJqVdaHgowBTMS0ijlZFfonQC/C1PrZOjD4xRCYgBqH9yttEATGE/nw==", "dev": true, "requires": { + "@octokit/openapi-types": "^2.0.1", "@types/node": ">= 8" } }, "@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz", + "integrity": "sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==", "requires": { "type-detect": "4.0.8" } @@ -1554,15 +1764,15 @@ "dev": true }, "@types/minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", + "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==", "dev": true }, "@types/node": { - "version": "14.11.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.1.tgz", - "integrity": "sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw==", + "version": "14.14.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.14.tgz", + "integrity": "sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ==", "dev": true }, "@types/normalize-package-data": { @@ -1782,9 +1992,9 @@ "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" }, "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, "agent-base": { @@ -1822,9 +2032,9 @@ "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" }, "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" }, "amdefine": { "version": "1.0.1", @@ -1850,12 +2060,9 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "any-promise": { "version": "1.3.0", @@ -1867,7 +2074,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "optional": true, "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" @@ -1877,7 +2083,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "optional": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -2001,21 +2206,13 @@ } }, "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } + "minimalistic-assert": "^1.0.0" } }, "assert": { @@ -2064,19 +2261,10 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - }, "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "optional": true + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" }, "asynckit": { "version": "0.4.0", @@ -2102,9 +2290,9 @@ "dev": true }, "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, "axios": { @@ -2114,13 +2302,6 @@ "requires": { "follow-redirects": "1.5.10", "is-buffer": "^2.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" - } } }, "babel-code-frame": { @@ -2131,30 +2312,6 @@ "chalk": "^1.1.3", "esutils": "^2.0.2", "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } } }, "babel-helper-builder-binary-assignment-operator-visitor": { @@ -2699,11 +2856,6 @@ "requires": { "ms": "2.0.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -2806,8 +2958,7 @@ "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "optional": true + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" }, "bindings": { "version": "1.5.0", @@ -2819,14 +2970,14 @@ } }, "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", + "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==" }, "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "brace-expansion": { "version": "1.1.11", @@ -2915,46 +3066,20 @@ "requires": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } } }, "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" } }, "browserify-zlib": { @@ -2981,9 +3106,9 @@ "dev": true }, "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "requires": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", @@ -3024,9 +3149,9 @@ "dev": true }, "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", "requires": { "bluebird": "^3.5.5", "chownr": "^1.1.1", @@ -3046,9 +3171,9 @@ }, "dependencies": { "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3132,9 +3257,9 @@ "dev": true }, "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" }, "camelcase-keys": { "version": "6.2.2", @@ -3145,12 +3270,20 @@ "camelcase": "^5.3.1", "map-obj": "^4.0.0", "quick-lru": "^4.0.1" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } } }, "caniuse-lite": { - "version": "1.0.30001133", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001133.tgz", - "integrity": "sha512-s3XAUFaC/ntDb1O3lcw9K8MPeOW7KO3z9+GzAoBxfz1B0VdacXPMKgFUtG4KIsgmnbexmi013s9miVu4h+qMHw==" + "version": "1.0.30001040", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001040.tgz", + "integrity": "sha512-Ep0tEPeI5wCvmJNrXjE3etgfI+lkl1fTDU6Y3ZH1mhrjkPlVI9W4pcKbMo+BQLpEWKVYYp2EmYaRsqpPC3k7lQ==" }, "caseless": { "version": "0.12.0", @@ -3194,13 +3327,15 @@ "integrity": "sha1-xVEoN4+bs5nplPAAUhUZhO1uvnA=" }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "chardet": { @@ -3218,7 +3353,6 @@ "version": "2.1.8", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "optional": true, "requires": { "anymatch": "^2.0.0", "async-each": "^1.0.1", @@ -3235,9 +3369,9 @@ } }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" }, "chrome-trace-event": { "version": "1.0.2", @@ -3293,57 +3427,32 @@ } }, "cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ansi-regex": "^3.0.0" } } } @@ -3379,15 +3488,6 @@ "object-visit": "^1.0.0" } }, - "color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -3401,33 +3501,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "colornames": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", - "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" - }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", - "requires": { - "color": "3.0.x", - "text-hex": "1.0.x" - } + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true }, "columnify": { "version": "1.5.4", @@ -3533,9 +3611,9 @@ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" }, "conventional-changelog-angular": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.11.tgz", - "integrity": "sha512-nSLypht/1yEflhuTogC03i7DX7sOrXGsRn14g131Potqi6cbGbGEE9PSDEHKldabB6N76HiSyw9Ph+kLmC04Qw==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.12.tgz", + "integrity": "sha512-5GLsbnkR/7A89RyHLvvoExbiGbd9xKdKqDTrArnPbOqBqG/2wIosu0fHwpeIRI8Tl94MhVNBXcLJZl92ZQ5USw==", "dev": true, "requires": { "compare-func": "^2.0.0", @@ -3563,15 +3641,6 @@ "through2": "^3.0.0" }, "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -3584,40 +3653,6 @@ "strip-bom": "^3.0.0" } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -3689,39 +3724,49 @@ "dev": true }, "conventional-changelog-writer": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.17.tgz", - "integrity": "sha512-IKQuK3bib/n032KWaSb8YlBFds+aLmzENtnKtxJy3+HqDq5kohu3g/UdNbIHeJWygfnEbZjnCKFxAW0y7ArZAw==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.18.tgz", + "integrity": "sha512-mAQDCKyB9HsE8Ko5cCM1Jn1AWxXPYV0v8dFPabZRkvsiWUul2YyAqbIaoMKF88Zf2ffnOPSvKhboLf3fnjo5/A==", "dev": true, "requires": { "compare-func": "^2.0.0", - "conventional-commits-filter": "^2.0.6", + "conventional-commits-filter": "^2.0.7", "dateformat": "^3.0.0", "handlebars": "^4.7.6", "json-stringify-safe": "^5.0.1", "lodash": "^4.17.15", - "meow": "^7.0.0", + "meow": "^8.0.0", "semver": "^6.0.0", "split": "^1.0.0", - "through2": "^3.0.0" + "through2": "^4.0.0" }, "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" + "readable-stream": "3" } } } }, "conventional-commits-filter": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.6.tgz", - "integrity": "sha512-4g+sw8+KA50/Qwzfr0hL5k5NWxqtrOVw4DDk3/h6L85a9Gz0/Eqp3oP+CWCNfesBvZZZEFHF7OTEbRe+yYSyKw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", "dev": true, "requires": { "lodash.ismatch": "^4.4.0", @@ -3729,28 +3774,38 @@ } }, "conventional-commits-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.1.0.tgz", - "integrity": "sha512-RSo5S0WIwXZiRxUGTPuYFbqvrR4vpJ1BDdTlthFgvHt5kEdnd1+pdvwWphWn57/oIl4V72NMmOocFqqJ8mFFhA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.0.tgz", + "integrity": "sha512-XmJiXPxsF0JhAKyfA2Nn+rZwYKJ60nanlbSWwwkGwLQFbugsc0gv1rzc7VbbUWAzJfR1qR87/pNgv9NgmxtBMQ==", "dev": true, "requires": { "JSONStream": "^1.0.4", "is-text-path": "^1.0.1", "lodash": "^4.17.15", - "meow": "^7.0.0", + "meow": "^8.0.0", "split2": "^2.0.0", - "through2": "^3.0.0", + "through2": "^4.0.0", "trim-off-newlines": "^1.0.0" }, "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" + "readable-stream": "3" } } } @@ -3771,12 +3826,6 @@ "q": "^1.5.1" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, "camelcase-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", @@ -3800,15 +3849,6 @@ "typedarray": "^0.0.6" } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", @@ -3827,16 +3867,6 @@ "strip-bom": "^3.0.0" } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, "map-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", @@ -3870,30 +3900,6 @@ "is-plain-obj": "^1.1.0" } }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -3988,9 +3994,9 @@ } }, "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", "dev": true, "requires": { "safe-buffer": "~5.1.1" @@ -4055,12 +4061,6 @@ "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true } } }, @@ -4092,19 +4092,12 @@ } }, "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "requires": { "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } + "elliptic": "^6.0.0" } }, "create-hash": { @@ -4395,16 +4388,6 @@ "wrappy": "1" } }, - "diagnostics": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", - "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", - "requires": { - "colorspace": "1.1.x", - "enabled": "1.0.x", - "kuler": "1.0.x" - } - }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -4418,13 +4401,6 @@ "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } } }, "dir-glob": { @@ -4475,6 +4451,11 @@ "is-obj": "^1.0.0" } }, + "drange": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==" + }, "duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -4503,14 +4484,14 @@ } }, "electron-to-chromium": { - "version": "1.3.570", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.570.tgz", - "integrity": "sha512-Y6OCoVQgFQBP5py6A/06+yWxUZHDlNr/gNDGatjH8AZqXl8X0tE4LfjLJsXGz/JmWJz8a6K7bR1k+QzZ+k//fg==" + "version": "1.3.401", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.401.tgz", + "integrity": "sha512-9tvSOS1++0EQP0tkgyD8KJergVZsld1/UqOusZVTbx9MWZHw5NCezkOjIQ5YWeB45jKdQerDfRrt28HwidI9Ow==" }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -4519,13 +4500,6 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } } }, "emoji-regex": { @@ -4538,14 +4512,6 @@ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" }, - "enabled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", - "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", - "requires": { - "env-variable": "0.0.x" - } - }, "encoding": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", @@ -4575,9 +4541,9 @@ } }, "enhanced-resolve": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", - "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", "requires": { "graceful-fs": "^4.1.2", "memory-fs": "^0.5.0", @@ -4607,11 +4573,6 @@ "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", "dev": true }, - "env-variable": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", - "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==" - }, "envinfo": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.3.tgz", @@ -4650,27 +4611,26 @@ } }, "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", + "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", "requires": { - "es-to-primitive": "^1.2.1", + "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.0", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-inspect": "^1.6.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" } }, "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -4821,12 +4781,12 @@ }, "dependencies": { "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" @@ -4858,12 +4818,6 @@ "supports-color": "^5.3.0" } }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -4906,35 +4860,35 @@ } }, "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", + "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", "dev": true, "requires": { - "eslint-visitor-keys": "^1.1.0" + "eslint-visitor-keys": "^1.0.0" } }, "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", "dev": true }, "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.1.tgz", + "integrity": "sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==", "dev": true, "requires": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", + "acorn": "^7.0.0", + "acorn-jsx": "^5.0.2", "eslint-visitor-keys": "^1.1.0" }, "dependencies": { "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", "dev": true } } @@ -4945,35 +4899,20 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } + "estraverse": "^4.0.0" } }, "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" - } + "estraverse": "^4.1.0" } }, "estraverse": { @@ -4993,9 +4932,9 @@ "dev": true }, "events": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==" }, "evp_bytestokey": { "version": "1.0.3", @@ -5057,11 +4996,6 @@ "requires": { "is-extendable": "^0.1.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -5205,9 +5139,9 @@ } }, "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", @@ -5215,20 +5149,10 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" - }, - "fecha": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", - "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" - }, "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" }, "figures": { "version": "2.0.0", @@ -5320,11 +5244,11 @@ } }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "requires": { - "locate-path": "^3.0.0" + "locate-path": "^2.0.0" } }, "findup-sync": { @@ -5344,13 +5268,6 @@ "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", "requires": { "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" - } } }, "flat-cache": { @@ -5376,9 +5293,9 @@ } }, "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", "dev": true }, "flush-write-stream": { @@ -5405,11 +5322,6 @@ "requires": { "ms": "2.0.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -5532,13 +5444,553 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", + "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", "optional": true, "requires": { "bindings": "^1.5.0", - "nan": "^2.12.1" + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true + }, + "aproba": { + "version": "1.2.0", + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": false, + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": false, + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": false, + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "optional": true + }, + "debug": { + "version": "3.2.6", + "resolved": false, + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": false, + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": false, + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": false, + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "optional": true + }, + "gauge": { + "version": "2.7.4", + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": false, + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": false, + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": false, + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": false, + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "optional": true + }, + "ini": { + "version": "1.3.5", + "resolved": false, + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": false, + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "optional": true + }, + "minipass": { + "version": "2.9.0", + "resolved": false, + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": false, + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.3", + "resolved": false, + "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": false, + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "needle": { + "version": "2.3.3", + "resolved": false, + "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "resolved": false, + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.3", + "resolved": false, + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "optional": true + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": false, + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "optional": true + }, + "osenv": { + "version": "0.1.5", + "resolved": false, + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "optional": true + }, + "rc": { + "version": "1.2.8", + "resolved": false, + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": false, + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": false, + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": false, + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": false, + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": false, + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "optional": true + }, + "semver": { + "version": "5.7.1", + "resolved": false, + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "optional": true + }, + "string-width": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "optional": true + }, + "tar": { + "version": "4.4.13", + "resolved": false, + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": false, + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true + }, + "yallist": { + "version": "3.1.1", + "resolved": false, + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "optional": true + } } }, "function-bind": { @@ -5742,12 +6194,6 @@ "through2": "^2.0.0" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, "camelcase-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", @@ -5759,15 +6205,6 @@ "quick-lru": "^1.0.0" } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", @@ -5786,16 +6223,6 @@ "strip-bom": "^3.0.0" } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, "map-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", @@ -5829,30 +6256,6 @@ "is-plain-obj": "^1.1.0" } }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -5963,12 +6366,6 @@ "semver": "^6.0.0" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, "camelcase-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", @@ -5980,15 +6377,6 @@ "quick-lru": "^1.0.0" } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, "indent-string": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", @@ -6007,16 +6395,6 @@ "strip-bom": "^3.0.0" } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, "map-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", @@ -6050,30 +6428,6 @@ "is-plain-obj": "^1.1.0" } }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -6167,9 +6521,9 @@ } }, "git-url-parse": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.2.0.tgz", - "integrity": "sha512-KPoHZg8v+plarZvto4ruIzzJLFQoRx+sUs5DQSr07By9IBKguVd+e6jwrFR6/TP6xrCJlNV1tPqLO1aREc7O2g==", + "version": "11.4.3", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.4.3.tgz", + "integrity": "sha512-LZTTk0nqJnKN48YRtOpR8H5SEfp1oM2tls90NuZmBxN95PnCvmuXGzqQ4QmVirBgKx2KPYfPGteX3/raWjKenQ==", "dev": true, "requires": { "git-up": "^4.0.0" @@ -6284,9 +6638,9 @@ } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" }, "growl": { "version": "1.10.5", @@ -6321,32 +6675,26 @@ "dev": true }, "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, "requires": { - "ajv": "^6.12.3", + "ajv": "^6.5.5", "har-schema": "^2.0.0" }, "dependencies": { "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true } } }, @@ -6378,9 +6726,9 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" }, "has-unicode": { "version": "2.0.1", @@ -6407,6 +6755,11 @@ "kind-of": "^4.0.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -6418,30 +6771,12 @@ } }, "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "hash.js": { @@ -6486,9 +6821,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", "dev": true }, "html-escaper": { @@ -6521,12 +6856,6 @@ "requires": { "ms": "2.0.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, @@ -6557,13 +6886,19 @@ }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true } } }, @@ -6611,9 +6946,9 @@ } }, "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -6795,6 +7130,11 @@ "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -6805,29 +7145,23 @@ } } }, - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "optional": true, "requires": { "binary-extensions": "^1.0.0" } }, "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" }, "is-callable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", - "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, "is-ci": { "version": "2.0.0", @@ -6838,6 +7172,15 @@ "ci-info": "^2.0.0" } }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -6846,6 +7189,11 @@ "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -6857,9 +7205,9 @@ } }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-descriptor": { "version": "0.1.6", @@ -6913,11 +7261,6 @@ "is-extglob": "^2.1.1" } }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -6926,6 +7269,11 @@ "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -6956,12 +7304,18 @@ "isobject": "^3.0.1" } }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "requires": { - "has-symbols": "^1.0.1" + "has": "^1.0.1" } }, "is-ssh": { @@ -6979,11 +7333,11 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.0" } }, "is-text-path": { @@ -7353,12 +7707,12 @@ } }, "js2xmlparser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", - "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.0.tgz", + "integrity": "sha512-WuNgdZOXVmBk5kUPMcTcVUpbGRzLfNkv7+7APq7WiDihpXVKrgxo6wwRpRl9OQeEBgKCVk9mR7RbzrnNWC8oBw==", "dev": true, "requires": { - "xmlcreate": "^2.0.3" + "xmlcreate": "^2.0.0" } }, "jsbn": { @@ -7396,9 +7750,9 @@ "dev": true }, "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true } } @@ -7418,70 +7772,30 @@ "yargs": "^11.0.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "p-try": "^1.0.0" + "color-convert": "^1.9.0" } }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { - "p-limit": "^1.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "requires": { - "ansi-regex": "^3.0.0" + "has-flag": "^3.0.0" } }, "yargs": { @@ -7581,9 +7895,9 @@ } }, "just-extend": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", + "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==" }, "kind-of": { "version": "6.0.3", @@ -7598,14 +7912,6 @@ "graceful-fs": "^4.1.9" } }, - "kuler": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", - "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", - "requires": { - "colornames": "^1.1.1" - } - }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -7717,18 +8023,18 @@ } }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "requires": { - "p-locate": "^3.0.0", + "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lodash._reinterpolate": { "version": "3.0.0", @@ -7815,18 +8121,34 @@ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "requires": { "chalk": "^2.0.1" - } - }, - "logform": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", - "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", - "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "triple-beam": "^1.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, "lolex": { @@ -7955,9 +8277,9 @@ } }, "markdown-it-anchor": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", - "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz", + "integrity": "sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ==", "dev": true }, "marked": { @@ -8002,9 +8324,9 @@ } }, "meow": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz", - "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.0.0.tgz", + "integrity": "sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg==", "dev": true, "requires": { "@types/minimist": "^1.2.0", @@ -8012,12 +8334,12 @@ "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", - "normalize-package-data": "^2.5.0", + "normalize-package-data": "^3.0.0", "read-pkg-up": "^7.0.1", "redent": "^3.0.0", "trim-newlines": "^3.0.0", - "type-fest": "^0.13.1", - "yargs-parser": "^18.1.3" + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" }, "dependencies": { "find-up": { @@ -8030,6 +8352,15 @@ "path-exists": "^4.0.0" } }, + "hosted-git-info": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz", + "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -8039,6 +8370,36 @@ "p-locate": "^4.1.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "normalize-package-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", + "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", + "dev": true, + "requires": { + "hosted-git-info": "^3.0.6", + "resolve": "^1.17.0", + "semver": "^7.3.2", + "validate-npm-package-license": "^3.0.1" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -8048,6 +8409,12 @@ "p-limit": "^2.2.0" } }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "parse-json": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", @@ -8078,6 +8445,30 @@ "type-fest": "^0.6.0" }, "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", @@ -8105,21 +8496,42 @@ } } }, - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "lru-cache": "^6.0.0" } + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true } } }, @@ -8173,28 +8585,21 @@ "requires": { "bn.js": "^4.0.0", "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } } }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", "dev": true }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "dev": true, "requires": { - "mime-db": "1.44.0" + "mime-db": "1.40.0" } }, "mimic-fn": { @@ -8352,30 +8757,14 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "cliui": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - } - } + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "debug": { "version": "3.2.6", @@ -8385,27 +8774,54 @@ "ms": "^2.1.1" } }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" } }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -8419,29 +8835,14 @@ "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" } }, "supports-color": { @@ -8522,9 +8923,9 @@ "integrity": "sha1-/A2ixlR31yXKa5Z51YNw7QxS9Ts=" }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multimatch": { "version": "3.0.0", @@ -8556,9 +8957,9 @@ } }, "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "optional": true }, "nanomatch": { @@ -8586,9 +8987,9 @@ "dev": true }, "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" }, "nested-error-stacks": { "version": "2.1.0", @@ -8613,6 +9014,14 @@ "path-to-regexp": "^1.7.0" }, "dependencies": { + "@sinonjs/commons": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.2.tgz", + "integrity": "sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw==", + "requires": { + "type-detect": "4.0.8" + } + }, "lolex": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", @@ -8766,9 +9175,9 @@ }, "dependencies": { "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -8785,8 +9194,7 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "optional": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "normalize-url": { "version": "3.3.0", @@ -8817,6 +9225,14 @@ "uid-number": "0.0.6", "umask": "^1.1.0", "which": "^1.3.1" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } } }, "npm-normalize-package-bin": { @@ -9047,9 +9463,9 @@ } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -9077,9 +9493,9 @@ "dev": true }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -9117,6 +9533,11 @@ "is-descriptor": "^0.1.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -9128,9 +9549,9 @@ } }, "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" }, "object-keys": { "version": "1.1.1", @@ -9146,44 +9567,23 @@ } }, "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } }, "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" } }, "object.pick": { @@ -9208,11 +9608,6 @@ "wrappy": "1" } }, - "one-time": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", - "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" - }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", @@ -9231,17 +9626,17 @@ } }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", + "fast-levenshtein": "~2.0.4", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "wordwrap": "~1.0.0" } }, "os-browserify": { @@ -9307,19 +9702,19 @@ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "requires": { - "p-try": "^2.0.0" + "p-try": "^1.0.0" } }, "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "requires": { - "p-limit": "^2.0.0" + "p-limit": "^1.1.0" } }, "p-map": { @@ -9359,9 +9754,9 @@ "dev": true }, "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "p-waterfall": { "version": "1.0.0", @@ -9409,12 +9804,13 @@ } }, "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", "requires": { - "asn1.js": "^5.2.0", + "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3", "safe-buffer": "^5.1.1" @@ -9538,9 +9934,9 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, "pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -9560,12 +9956,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "optional": true - }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -9645,9 +10035,9 @@ } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", "requires": { "p-try": "^2.0.0" } @@ -9761,9 +10151,9 @@ "dev": true }, "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", + "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==", "dev": true }, "public-encrypt": { @@ -9777,13 +10167,6 @@ "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" - } } }, "pump": { @@ -9849,6 +10232,22 @@ "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true }, + "randexp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz", + "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==", + "requires": { + "drange": "^1.0.2", + "ret": "^0.2.0" + }, + "dependencies": { + "ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==" + } + } + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -9950,9 +10349,9 @@ } }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -9979,7 +10378,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "optional": true, "requires": { "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", @@ -9997,9 +10395,9 @@ } }, "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" }, "regenerator-runtime": { "version": "0.11.1", @@ -10066,8 +10464,7 @@ "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "optional": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { "version": "1.1.3", @@ -10089,9 +10486,9 @@ } }, "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "requires": { "aws-sign2": "~0.7.0", @@ -10101,7 +10498,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.3", + "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -10111,7 +10508,7 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" } @@ -10147,13 +10544,6 @@ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "requires": { "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" - } } }, "resolve-dir": { @@ -10178,10 +10568,9 @@ } }, "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, "resolve-url": { "version": "0.2.1", @@ -10227,10 +10616,13 @@ } }, "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } }, "run-queue": { "version": "1.0.3", @@ -10241,9 +10633,9 @@ } }, "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -10265,7 +10657,8 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "schema-utils": { "version": "1.0.0", @@ -10284,12 +10677,9 @@ "dev": true }, "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "requires": { - "randombytes": "^2.1.0" - } + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" }, "set-blocking": { "version": "2.0.0", @@ -10354,17 +10744,9 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "requires": { - "is-arrayish": "^0.3.1" - } + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "sinon": { "version": "7.3.2", @@ -10378,6 +10760,16 @@ "lolex": "^4.0.1", "nise": "^1.4.10", "supports-color": "^5.5.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } } }, "sinon-chai": { @@ -10462,11 +10854,6 @@ "requires": { "is-extendable": "^0.1.0" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -10524,6 +10911,11 @@ "kind-of": "^3.2.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -10585,11 +10977,11 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "requires": { - "atob": "^2.1.2", + "atob": "^2.1.1", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -10597,9 +10989,9 @@ } }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -10632,9 +11024,9 @@ } }, "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -10642,15 +11034,15 @@ } }, "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -10719,11 +11111,6 @@ "figgy-pudding": "^3.5.1" } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -10774,9 +11161,9 @@ } }, "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" }, "string-width": { "version": "2.1.1", @@ -10802,22 +11189,22 @@ } } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "function-bind": "^1.1.1" } }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" + "function-bind": "^1.1.1" } }, "string_decoder": { @@ -10876,12 +11263,9 @@ } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, "symbol": { "version": "0.2.3", @@ -10902,12 +11286,12 @@ }, "dependencies": { "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" @@ -10919,12 +11303,6 @@ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -11011,9 +11389,9 @@ } }, "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "4.6.11", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.11.tgz", + "integrity": "sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==", "requires": { "commander": "^2.20.0", "source-map": "~0.6.1", @@ -11028,15 +11406,15 @@ } }, "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", "requires": { "cacache": "^12.0.2", "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", + "serialize-javascript": "^2.1.2", "source-map": "^0.6.1", "terser": "^4.1.2", "webpack-sources": "^1.4.0", @@ -11094,9 +11472,9 @@ } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -11183,11 +11561,6 @@ "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, - "text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -11269,6 +11642,11 @@ "kind-of": "^3.0.2" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -11300,13 +11678,21 @@ } }, "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } } }, "tr46": { @@ -11330,15 +11716,10 @@ "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", "dev": true }, - "triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" - }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" }, "tty-browserify": { "version": "0.0.0", @@ -11392,11 +11773,31 @@ "dev": true }, "uglify-js": { - "version": "3.10.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.4.tgz", - "integrity": "sha512-kBFT3U4Dcj4/pJ52vfjCSfyLyvG9VYYuGYPmrPvAxRw/i7xHiT4VvCev+uiEMcEEiu6UNB6KgWmGtSUYIWScbw==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.1.tgz", + "integrity": "sha512-W7KxyzeaQmZvUFbGj4+YFshhVrMBGSg2IbcYAjGWGvx8DHvJMclbTDMpffdxFUGPBHjIytk7KJUR/KUXstUGDw==", "dev": true, - "optional": true + "optional": true, + "requires": { + "commander": "~2.20.3", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } }, "uid-number": { "version": "0.0.6", @@ -11411,9 +11812,9 @@ "dev": true }, "underscore": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", - "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", "dev": true }, "union-value": { @@ -11499,9 +11900,9 @@ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "requires": { "punycode": "^2.1.0" } @@ -11612,123 +12013,13 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" }, "watchpack": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", - "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz", + "integrity": "sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA==", "requires": { - "chokidar": "^3.4.1", + "chokidar": "^2.1.8", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "optional": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "optional": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "optional": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "optional": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "optional": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "optional": true - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "optional": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "optional": true - }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "optional": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "optional": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "watchpack-chokidar2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", - "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", - "optional": true, - "requires": { - "chokidar": "^2.1.8" + "neo-async": "^2.5.0" } }, "wcwidth": { @@ -11802,6 +12093,34 @@ "yargs": "13.2.4" }, "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -11899,49 +12218,6 @@ "execa": "^1.0.0" } }, - "winston": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", - "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", - "requires": { - "async": "^2.6.1", - "diagnostics": "^1.1.1", - "is-stream": "^1.1.0", - "logform": "^2.1.1", - "one-time": "0.0.4", - "readable-stream": "^3.1.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.3.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "winston-transport": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", - "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", - "requires": { - "readable-stream": "^2.3.7", - "triple-beam": "^1.2.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -12066,9 +12342,9 @@ } }, "xmlcreate": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", - "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.1.tgz", + "integrity": "sha512-MjGsXhKG8YjTKrDCXseFo3ClbMGvUD4en29H2Cev1dv4P/chlpw6KdYmlCWDkhosBVKRDjM836+3e3pm1cBNJA==", "dev": true }, "xtend": { @@ -12155,9 +12431,9 @@ } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", "requires": { "p-try": "^2.0.0" } @@ -12214,9 +12490,9 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -12232,6 +12508,14 @@ "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } } }, "yargs-unparser": { @@ -12244,29 +12528,49 @@ "yargs": "^12.0.5" }, "dependencies": { - "ansi-regex": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "find-up": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { - "ansi-regex": "^3.0.0" + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" } }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, "yargs": { "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", diff --git a/package.json b/package.json index 7cc4341a49..58e56a07c7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "private": true, "devDependencies": { - "colors": "^1.4.0", + "colors": "1.4.0", + "eslint": "6.0.1", "coveralls": "3.0.4", "eslint": "6.0.1", "istanbul-combine": "0.3.0", @@ -94,4 +95,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/concerto-cli/index.js b/packages/concerto-cli/index.js index c76a554787..931cfe3279 100755 --- a/packages/concerto-cli/index.js +++ b/packages/concerto-cli/index.js @@ -29,10 +29,6 @@ require('yargs') describe: 'sample JSON to validate', type: 'string' }); - yargs.option('ctoSystem', { - describe: 'system model to be used', - type: 'string' - }); yargs.option('ctoFiles', { describe: 'array of CTO files', type: 'string', @@ -52,7 +48,7 @@ require('yargs') argv = Commands.validateValidateArgs(argv); const options = {}; options.offline = argv.offline; - return Commands.validate(argv.sample, argv.ctoSystem, argv.ctoFiles, options) + return Commands.validate(argv.sample, argv.ctoFiles, options) .then((result) => { Logger.info(result); }) @@ -66,10 +62,6 @@ require('yargs') }) .command('compile', 'generate code for a target platform', (yargs) => { yargs.demandOption(['ctoFiles'], 'Please provide at least the CTO files'); - yargs.option('ctoSystem', { - describe: 'system model to be used', - type: 'string' - }); yargs.option('ctoFiles', { describe: 'array of CTO files', type: 'string', @@ -97,7 +89,7 @@ require('yargs') const options = {}; options.offline = argv.offline; - return Commands.compile(argv.target, argv.ctoSystem, argv.ctoFiles, argv.output, options) + return Commands.compile(argv.target, argv.ctoFiles, argv.output, options) .then((result) => { Logger.info(result); }) @@ -112,10 +104,6 @@ require('yargs') type: 'string', array: true }); - yargs.option('ctoSystem', { - describe: 'system model to be used', - type: 'string' - }); yargs.option('output', { describe: 'output directory path', type: 'string', @@ -126,7 +114,7 @@ require('yargs') Logger.info(`saving external models from ${argv.ctoFiles} into directory: ${argv.output}`); } - return Commands.get(argv.ctoSystem, argv.ctoFiles, argv.output) + return Commands.get(argv.ctoFiles, argv.output) .then((result) => { Logger.info(result); }) diff --git a/packages/concerto-cli/lib/commands.js b/packages/concerto-cli/lib/commands.js index 2b1fbbff21..6bf6459fb5 100644 --- a/packages/concerto-cli/lib/commands.js +++ b/packages/concerto-cli/lib/commands.js @@ -97,16 +97,15 @@ class Commands { * Validate a sample JSON against the model * * @param {string} sample - the sample to validate - * @param {string} ctoSystemFile - the system model file * @param {string[]} ctoFiles - the CTO files to convert to code * @param {object} options - optional parameters * @param {boolean} [options.offline] - do not resolve external models * @returns {string} serialized form of the validated JSON */ - static async validate(sample, ctoSystemFile, ctoFiles, options) { + static async validate(sample, ctoFiles, options) { const json = JSON.parse(fs.readFileSync(sample, 'utf8')); - const modelManager = await ModelLoader.loadModelManager(ctoSystemFile, ctoFiles, options); + const modelManager = await ModelLoader.loadModelManager(ctoFiles, options); const factory = new Factory(modelManager); const serializer = new Serializer(factory, modelManager); @@ -118,14 +117,13 @@ class Commands { * Compile the model for a given target * * @param {string} target - the target of the code to compile - * @param {string} ctoSystemFile - the system model file * @param {string[]} ctoFiles - the CTO files to convert to code * @param {string} output the output directory * @param {object} options - optional parameters * @param {boolean} [options.offline] - do not resolve external models */ - static async compile(target, ctoSystemFile, ctoFiles, output, options) { - const modelManager = await ModelLoader.loadModelManager(ctoSystemFile, ctoFiles, options); + static async compile(target, ctoFiles, output, options) { + const modelManager = await ModelLoader.loadModelManager(ctoFiles, options); let visitor = null; @@ -165,12 +163,11 @@ class Commands { * Fetches all external for a set of models dependencies and * saves all the models to a target directory * - * @param {string} ctoSystemFile the system model * @param {string[]} ctoFiles the CTO files (can be local file paths or URLs) * @param {string} output the output directory */ - static async get(ctoSystemFile, ctoFiles, output) { - const modelManager = await ModelLoader.loadModelManager(ctoSystemFile, ctoFiles); + static async get(ctoFiles, output) { + const modelManager = await ModelLoader.loadModelManager(ctoFiles); mkdirp.sync(output); modelManager.writeModelsToFileSystem(output); return `Loaded external models in '${output}'.`; diff --git a/packages/concerto-cli/test/cli.js b/packages/concerto-cli/test/cli.js index dd09b1e750..55f909f57a 100644 --- a/packages/concerto-cli/test/cli.js +++ b/packages/concerto-cli/test/cli.js @@ -28,7 +28,6 @@ const Commands = require('../lib/commands'); describe('cicero-cli', () => { const models = [path.resolve(__dirname, 'models/dom.cto'),path.resolve(__dirname, 'models/money.cto')]; const offlineModels = [path.resolve(__dirname, 'models/contract.cto'),path.resolve(__dirname, 'models/dom.cto'),path.resolve(__dirname, 'models/money.cto')]; - const hlModel = path.resolve(__dirname, 'models/org.hyperledger.composer.system.cto'); const sample1 = path.resolve(__dirname, 'data/sample1.json'); const sample2 = path.resolve(__dirname, 'data/sample2.json'); const sampleText1 = fs.readFileSync(sample1, 'utf8'); @@ -55,30 +54,30 @@ describe('cicero-cli', () => { describe('#validate', () => { it('should validate against a model', async () => { - const result = await Commands.validate(sample1, null, models, {offline:false}); + const result = await Commands.validate(sample1, models, {offline:false}); JSON.parse(result).should.deep.equal(JSON.parse(sampleText1)); }); it('should fail to validate against a model', async () => { try { - const result = await Commands.validate(sample2, null, models, {offline:false}); + const result = await Commands.validate(sample2, models, {offline:false}); JSON.parse(result).should.deep.equal(JSON.parse(sampleText2)); } catch (err) { - err.message.should.equal('Instance undefined invalid enum value true for field CurrencyCode'); + err.message.should.equal('Instance org.accordproject.money.MonetaryAmount#null invalid enum value true for field CurrencyCode'); } }); it('should validate against a model (offline)', async () => { - const result = await Commands.validate(sample1, null, offlineModels, {offline:true}); + const result = await Commands.validate(sample1, offlineModels, {offline:true}); JSON.parse(result).should.deep.equal(JSON.parse(sampleText1)); }); it('should fail to validate against a model (offline)', async () => { try { - const result = await Commands.validate(sample2, null, offlineModels, {offline:true}); + const result = await Commands.validate(sample2, offlineModels, {offline:true}); JSON.parse(result).should.deep.equal(JSON.parse(sampleText2)); } catch (err) { - err.message.should.equal('Instance undefined invalid enum value true for field CurrencyCode'); + err.message.should.equal('Instance org.accordproject.money.MonetaryAmount#null invalid enum value true for field CurrencyCode'); } }); @@ -111,43 +110,43 @@ describe('cicero-cli', () => { it('should compile to a Go model', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.compile('Go', null, models, dir.path, {offline:false}); + await Commands.compile('Go', models, dir.path, {offline:false}); fs.readdirSync(dir.path).length.should.be.above(0); dir.cleanup(); }); it('should compile to a PlantUML model', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.compile('PlantUML', null, models, dir.path, {offline:false}); + await Commands.compile('PlantUML', models, dir.path, {offline:false}); fs.readdirSync(dir.path).length.should.be.above(0); dir.cleanup(); }); it('should compile to a Typescript model', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.compile('Typescript', null, models, dir.path, {offline:false}); + await Commands.compile('Typescript', models, dir.path, {offline:false}); fs.readdirSync(dir.path).length.should.be.above(0); dir.cleanup(); }); it('should compile to a Java model', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.compile('Java', null, models, dir.path); + await Commands.compile('Java', models, dir.path); fs.readdirSync(dir.path).length.should.be.above(0); dir.cleanup(); }); it('should compile to a JSONSchema model', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.compile('JSONSchema', null, models, dir.path, {offline:false}); + await Commands.compile('JSONSchema', models, dir.path, {offline:false}); fs.readdirSync(dir.path).length.should.be.above(0); dir.cleanup(); }); it('should compile to a XMLSchema model', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.compile('XMLSchema', null, models, dir.path, {offline:false}); + await Commands.compile('XMLSchema', models, dir.path, {offline:false}); fs.readdirSync(dir.path).length.should.be.above(0); dir.cleanup(); }); it('should not compile to an unknown model', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.compile('BLAH', null, models, dir.path, {offline:false}); + await Commands.compile('BLAH', models, dir.path, {offline:false}); fs.readdirSync(dir.path).length.should.be.equal(0); dir.cleanup(); }); @@ -156,7 +155,7 @@ describe('cicero-cli', () => { describe('#get', () => { it('should save external dependencies', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.get(null, models, dir.path); + await Commands.get(models, dir.path); fs.readdirSync(dir.path).should.eql([ '@models.accordproject.org.cicero.contract.cto', 'dom.cto', @@ -167,7 +166,7 @@ describe('cicero-cli', () => { it('should save external dependencies for an external model', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); - await Commands.get(null,['https://models.accordproject.org/patents/patent.cto'], dir.path); + await Commands.get(['https://models.accordproject.org/patents/patent.cto'], dir.path); fs.readdirSync(dir.path).should.eql([ '@models.accordproject.org.address.cto', '@models.accordproject.org.geo.cto', @@ -181,14 +180,5 @@ describe('cicero-cli', () => { ]); dir.cleanup(); }); - - it('should fail saving external dependencies for an external model but with the wrong system model', async () => { - const dir = await tmp.dir({ unsafeCleanup: true}); - try { - await Commands.get(hlModel,['https://models.accordproject.org/patents/patent.cto'], dir.path); - } catch (err) { - err.message.should.contain('Relationship transactionInvoked must be to an asset or participant, but is to org.hyperledger.composer.system.Transaction'); - } - }); }); }); \ No newline at end of file diff --git a/packages/concerto-cli/test/models/org.hyperledger.composer.system.cto b/packages/concerto-cli/test/models/org.hyperledger.composer.system.cto deleted file mode 100644 index 30ebb993f9..0000000000 --- a/packages/concerto-cli/test/models/org.hyperledger.composer.system.cto +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -namespace org.hyperledger.composer.system - -/** - * Abstract system asset that all assets extend. - * Has no properties, and is soley used as a basis to model other assets. - */ -@docs('asset.md') -abstract asset Asset { } - -/** - * Abstract system participant that all participants extend. - * Has no properties, and is soley used as a basis to model other assets. - */ -@docs('participant.md') -abstract participant Participant { } - -/** - * Abstract transaction that all transactions, including system ones, extend. - * - * Has two properties that are used set and are accessible in all transactions. - * - * - * @param {String} transactionId Identifier for this transaction - */ -@docs('transaction.md') -abstract transaction Transaction identified by transactionId { - o String transactionId -} - -/** - * Abstract event that all events, including system ones, extend. - * - * Has two properties that are used set and are accessible in all transactions. - * - * @param {String} eventId Identifier for this event - */ -@docs('event.md') -abstract event Event identified by eventId { - o String eventId -} - -/** - * Abstract Registry asset, that is used as the basis for all types of registries. - * - * @param {String} registryId identity - * @param {String} name Name of the registry - * @param {String} type type of the registry - * @param {Boolean} system Is this a system registry? - */ -@docs('registry.md') -abstract asset Registry identified by registryId { - o String registryId - o String name - o String type - o Boolean system -} - -/** - * AssetRegistry extends the Registry to define the type that of all registries - * that are primarily intended for storing Assets. - * - */ -@docs('assetRegistry.md') -asset AssetRegistry extends Registry { } - -/** - * ParticipantRegistry extends the Registry to define the type that of all registries - * that are primarily intended for storing Participants - */ -@docs('participantRegistry.md') -asset ParticipantRegistry extends Registry { } - -/** - * TransactionRegistry extends the Registry to define the type that of all registries - * that are primarily intended for storing Transactions - */ -@docs('transactionRegistry.md') -asset TransactionRegistry extends Registry { } - - -/** - * Asset to represent the idea of a Business Network. - * All actions will require participants to have access to this Asset. Failure to have at least *READ* access - * will mean that participants are unable to access the network. - * - * Participants who are authorized administrators, can be granted *UPDATE* and/or *DELETE* permissions - - * @param {String} networkId of the business network - */ -@docs('network.md') -asset Network identified by networkId { - o String networkId - o String runtimeVersion -} - -/** - * A predefined participant that can be given the authority to adiminister the Business Network - * - * @param {String} participantId Identifier fields of the participant - */ -@docs('networkAdmin.md') -participant NetworkAdmin identified by participantId { - o String participantId -} - -// ----------------------------------------------------------------------------- -// Historian - -/** - * Asset to represent each historian registry entry - * - * @param {String} transactionId Using the transaction id as the uuid - * @param {Transaction} transactionInvoked Relationship to transaction - * @param {Participant} participantInvoking Participant who invoked this transaction - * @param {Identity} identityUsed The identity that was used by the participant - * @param {Event[]} eventsEmitted The events that were emitted by this transactionId - * @param {DateTime} transactionTimestamp Use the transaction's timestamp - */ -@docs('historian.md') -@docsuri('Composer Documentation','../business-network/historian') -asset HistorianRecord identified by transactionId { - o String transactionId - o String transactionType - --> Transaction transactionInvoked - --> Participant participantInvoking optional - --> Identity identityUsed optional - o Event[] eventsEmitted optional - o DateTime transactionTimestamp -} - -// ----------------------------------------------------------------------------- -// System transactions that act on Registries of any type -/** - * An abstract definition of a transaction that affects a registry in some way - * @param {Registry} targetRegistry Registry that will be manipulated - */ -@docs('registryTransaction.md') -abstract transaction RegistryTransaction { - --> Registry targetRegistry -} - -/** - * An abstract definition of a transaction that affects assets in a registry in some way - * @param {Asset[]} resources Resources that will be manipulated - */ -@docs('assetTransaction.md') -abstract transaction AssetTransaction extends RegistryTransaction { - o Asset[] resources -} - -/** - * An abstract definition of a transaction that affects participants in a registry in some way - * @param {Participant[]} resources participants that will be manipulated - */ -@docs('participantTransaction.md') -abstract transaction ParticipantTransaction extends RegistryTransaction { - o Participant[] resources -} - -/** - * Transaction that will add asset(s) to a registry - */ -transaction AddAsset extends AssetTransaction { } - -/** - * Transaction that will update asset(s) in a registry - */ -transaction UpdateAsset extends AssetTransaction { } - -/** - * Transaction that will remove asset(s) from a registry - * @param {String[]} resourceIds Identifiers of the assets to remove - */ -transaction RemoveAsset extends AssetTransaction { - o String[] resourceIds -} - -/** - * Transaction that will add participants(s) to a registry - */ -transaction AddParticipant extends ParticipantTransaction { } - -/** - * Transaction that will update participants(s) in a registry - */ -transaction UpdateParticipant extends ParticipantTransaction { } - -/** - * Transaction that will remove participants(s) from a registry - * @param {String[]} resourceIds Identifiers of the participants to remove - */ -transaction RemoveParticipant extends ParticipantTransaction { - o String[] resourceIds -} - - -// ----------------------------------------------------------------------------- -// Identity - -/** The valid states of an identity - * @enum {ISSUED} identity has been issued - * @enum {BOUND} identity has been bound to a participant - * @enum {ACTIVATED} identity has been activated - * @enum {REVOKED} identity has been revoked - */ -@docs('identityState.md') -enum IdentityState { - o ISSUED - o BOUND - o ACTIVATED - o REVOKED -} - -/** - * Asset representing the idea of an Identity - * - * @param {String} identityId Unique Identifiers - * @param {String} name Name given to this identity - * @param {String} issuer The issuer - * @param {String} certificate The certificate - * @param {IdentityState} state State the identity is in - * @param {Participant} participant Associated participant - */ -@docs('identity.md') -asset Identity identified by identityId { - o String identityId - o String name - o String issuer - o String certificate - o IdentityState state - --> Participant participant -} - -/** - * Transaction that will issue the identity - * @param {Participant} participant to issue the identity to - * @param {String} identityName name to use for this identity - */ -@docs('issueIdentity.md') -transaction IssueIdentity { - --> Participant participant - o String identityName -} - -/** - * Transaction that will bind the identity - * @param {Participant} participant to issue bind identity to - * @param {String} certificate to use - */ -@docs('bindIdentity.md') -transaction BindIdentity { - --> Participant participant - o String certificate -} - -/** - * Transaction that will activate the current the identity - */ -@docs('activateIdentity.md') -transaction ActivateCurrentIdentity { } - -/** - * Transaction that will revoke the identity - * @param {Identity} identity to revoke - */ -@docs('revokeIdentity.md') -transaction RevokeIdentity { - --> Identity identity -} - -/** - * Transaction that will Start a business network - * @param {Transaction[]} [bootstrapTransactions] optional transactions to use to bootstrap the network - * @param {String} [logLevel] Log level to use optionally - * - */ -@docs('startBusinessNetwork.md') -transaction StartBusinessNetwork { - o String logLevel optional - o Transaction[] bootstrapTransactions optional -} - -/** - * Transaction that will Reset a business network. This removes all the data but leaves the structure of the business network intact - */ -@docs('resetBusinessNetwork.md') -transaction ResetBusinessNetwork { - -} - -/** - * Sets the log level of the Business Network runtime to that specified - * @param {String} newLogLevel a valid debug string - */ -@docs('setLogLevel.md') -transaction SetLogLevel { - o String newLogLevel -} diff --git a/packages/concerto-core/api.txt b/packages/concerto-core/api.txt index eed82ed980..250f351ef0 100644 --- a/packages/concerto-core/api.txt +++ b/packages/concerto-core/api.txt @@ -7,6 +7,23 @@ class BaseFileException extends BaseException { + string getShortMessage() + string getFileName() } +class Concerto { + + void constructor() + + void validate(undefined) throws Error + + void getModelManager() + + boolean isObject() + + void getTypeDeclaration() + + string getIdentifier() + + boolean isIdentifiable() + + boolean isRelationship() + + void setIdentifier(string) + + string getFullyQualifiedIdentifier() + + string toURI() + + void fromURI(string) throws Error + + string getType() + + string getNamespace() + + boolean instanceOf(String) +} class Factory { + void constructor(ModelManager) + Resource newResource(String,String,String,Object,boolean,String,boolean,boolean) throws TypeNotFoundException @@ -16,27 +33,23 @@ class Factory { + Resource newEvent(String,String,String,Object,String,boolean,boolean) + boolean hasInstance(object) } -class AssetDeclaration extends ClassDeclaration { +class AssetDeclaration extends IdentifiedDeclaration { + void constructor(ModelFile,Object) throws IllegalModelException - + boolean isRelationshipTarget() - + string getSystemType() + boolean hasInstance(object) } class ClassDeclaration extends Decorated { + void constructor(ModelFile,string) throws IllegalModelException + ClassDeclaration _resolveSuperType() - + string getSystemType() + boolean isAbstract() + boolean isEnum() + boolean isConcept() + boolean isEvent() - + boolean isRelationshipTarget() - + boolean isSystemRelationshipTarget() - + boolean isSystemType() - + boolean isSystemCoreType() + string getName() + String getNamespace() + string getFullyQualifiedName() + + Boolean isIdentified() + + Boolean isSystemIdentified() + + Boolean isExplicitlyIdentified() + string getIdentifierFieldName() + Property getOwnProperty(string) + Property[] getOwnProperties() @@ -74,19 +87,23 @@ class EnumValueDeclaration extends Property { + void constructor(ClassDeclaration,Object) throws IllegalModelException + boolean hasInstance(object) } -class EventDeclaration extends ClassDeclaration { +class EventDeclaration extends IdentifiedDeclaration { + void constructor(ModelFile,Object) throws IllegalModelException - + string getSystemType() + boolean isEvent() + boolean hasInstance(object) } +class IdentifiedDeclaration extends ClassDeclaration { + + void constructor(ModelFile,Object) throws IllegalModelException + + boolean hasInstance(object) +} class Introspector { + void constructor(ModelManager) + ClassDeclaration[] getClassDeclarations() + ClassDeclaration getClassDeclaration(String) throws Error } class ModelFile { - + void constructor(ModelManager,string,string,boolean) throws IllegalModelException + + void constructor(ModelManager,string,string) throws IllegalModelException + + Boolean isSystemModelFile() + boolean isExternal() + ModelManager getModelManager() + string[] getImports() @@ -104,16 +121,13 @@ class ModelFile { + ParticipantDeclaration[] getParticipantDeclarations(Boolean) + ConceptDeclaration[] getConceptDeclarations(Boolean) + EnumDeclaration[] getEnumDeclarations(Boolean) - + ClassDeclaration[] getDeclarations(Function,Boolean) + + ClassDeclaration[] getDeclarations(Function) + ClassDeclaration[] getAllDeclarations() + string getDefinitions() - + boolean isSystemModelFile() + boolean hasInstance(object) } -class ParticipantDeclaration extends ClassDeclaration { +class ParticipantDeclaration extends IdentifiedDeclaration { + void constructor(ModelFile,Object) throws IllegalModelException - + boolean isRelationshipTarget() - + string getSystemType() + boolean hasInstance(object) } class Property extends Decorated { @@ -135,14 +149,10 @@ class RelationshipDeclaration extends Property { + String toString() + boolean hasInstance(object) } -class TransactionDeclaration extends ClassDeclaration { +class TransactionDeclaration extends IdentifiedDeclaration { + void constructor(ModelFile,Object) throws IllegalModelException - + string getSystemType() + boolean hasInstance(object) } -class Concept extends Typed { - + boolean isConcept() -} class Identifiable extends Typed { + string getIdentifier() + void setIdentifier(string) @@ -160,6 +170,8 @@ class Relationship extends Identifiable { class Resource extends Identifiable { + String toString() + boolean isResource() + + boolean isConcept() + + boolean isIdentifiable() + Object toJSON() } class Typed { @@ -170,34 +182,28 @@ class Typed { + void addArrayValue(string,string) + boolean instanceOf(String) } -class ValidatedConcept extends Concept { - + void setPropertyValue(string,string) throws Error - + void addArrayValue(string,string) throws Error - + void validate() throws Error -} class ValidatedResource extends Resource { + void setPropertyValue(string,string) throws Error + void addArrayValue(string,string) throws Error + void validate() throws Error } class ModelLoader { - + object loadModelManager(string,string[],object,boolean) - + object loadModelManagerFromModelFiles(string,object[],undefined,object,boolean) + + object loadModelManager(string[],object,boolean) + + object loadModelManagerFromModelFiles(object[],undefined,object,boolean) } class ModelManager { + void constructor() + void validateModelFile(string,string) throws IllegalModelException - + Object addModelFile(string,string,boolean,boolean) throws IllegalModelException + + Object addModelFile(string,string,boolean) throws IllegalModelException + Object updateModelFile(string,string,boolean) throws IllegalModelException + void deleteModelFile(string) - + Object[] addModelFiles(object[],undefined,boolean,boolean) + + Object[] addModelFiles(object[],undefined,boolean) + void validateModelFiles() + Promise updateExternalModels(Object,ModelFileDownloader) throws IllegalModelException - + void writeModelsToFileSystem(String,Object,boolean,boolean) - + Object[] getModels(Object,boolean,boolean) + + void writeModelsToFileSystem(String,Object,boolean) + + Object[] getModels(Object,boolean) + void clearModelFiles() + string[] getNamespaces() - + ClassDeclaration[] getSystemTypes() + AssetDeclaration[] getAssetDeclarations(Boolean) + TransactionDeclaration[] getTransactionDeclarations(Boolean) + EventDeclaration[] getEventDeclarations(Boolean) diff --git a/packages/concerto-core/changelog.txt b/packages/concerto-core/changelog.txt index 47749e5907..221b316c3e 100644 --- a/packages/concerto-core/changelog.txt +++ b/packages/concerto-core/changelog.txt @@ -24,15 +24,26 @@ # Note that the latest public API is documented using JSDocs and is available in api.txt. # +Version 0.82.12 {6b77ace6b34d454cc067aa5e204aa29b} 2020-12-25 +- Concepts may now be identified +- assets/participants/transaction/events have a system identified created $identifier automatically +- Can no longer redefine the identifier declared by a super type +- All types extend concerto.Concept +- Add new Concerto API +- Removed System Models APIs +- Remove notion of system table +- Remove user ability to change system model +- Update JsDoc for ModelManager.addModelFiles +- Add Logger API +- Add instanceof alternatives to Factory and Serializer +- 'concerto' namespace is now reserved and cannot be used by user code + Version 0.82.9 {c96bafdd4a2bb7402f6b520a0cefe537} 2020-09-09 - Add option parameters to ModelLoader Version 0.82.6 {03fa6481ffdf0e58cb110c6f24009d18} 2020-02-26 - Update JsDoc for ModelManager.addModelFiles -Version 0.82.5 {d4d49fabba1c6ce465c446e2dccad488} 2019-11-10 -- Add instance of alternatives to Factory and Serializer - Version 0.82.1 {dee013e99a3c2d6acc4eddfb00aad2a2} 2019-10-22 - Make several constructors public - Add model loader utility class diff --git a/packages/concerto-core/index.js b/packages/concerto-core/index.js index 0b7372dff4..89dceb1a28 100644 --- a/packages/concerto-core/index.js +++ b/packages/concerto-core/index.js @@ -25,7 +25,6 @@ module.exports.AssetDeclaration = require('./lib/introspect/assetdeclaration'); module.exports.BaseException = require('./lib/baseexception'); module.exports.BaseFileException = require('./lib/basefileexception'); module.exports.ClassDeclaration = require('./lib/introspect/classdeclaration'); -module.exports.Concept = require('./lib/model/concept'); module.exports.ConceptDeclaration = require('./lib/introspect/conceptdeclaration'); module.exports.EnumDeclaration = require('./lib/introspect/enumdeclaration'); module.exports.EnumValueDeclaration = require('./lib/introspect/enumvaluedeclaration'); @@ -53,3 +52,4 @@ module.exports.Typed = require('./lib/model/typed'); module.exports.TypedStack = require('./lib/serializer/typedstack'); module.exports.ModelUtil = require('./lib/modelutil'); module.exports.version = require('./package.json'); +module.exports.Concerto = require('./lib/concerto'); \ No newline at end of file diff --git a/packages/concerto-core/lib/concerto.js b/packages/concerto-core/lib/concerto.js new file mode 100644 index 0000000000..8e764135d0 --- /dev/null +++ b/packages/concerto-core/lib/concerto.js @@ -0,0 +1,235 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const URIJS = require('urijs'); +const RESOURCE_SCHEME = 'resource'; +const TypedStack = require('./serializer/typedstack'); +const ObjectValidator = require('./serializer/objectvalidator'); + +/** + * Runtime API for Concerto. + * + * @class + * @memberof module:concerto-core + */ +class Concerto { + + /** + * Create a Concerto instance. + * @param {*} modelManager - The this.modelManager to use for validation etc. + */ + constructor(modelManager) { + this.modelManager = modelManager; + } + + /** + * Validates the instance against its model. + * @param {*} obj the input object + * @param {*} [options] the validation options + * @throws {Error} - if the instance if invalid with respect to the model + */ + validate(obj, options) { + const classDeclaration = this.getTypeDeclaration(obj); + const parameters = {}; + parameters.stack = new TypedStack(obj); + const objectValidator = new ObjectValidator(this, options); + classDeclaration.accept(objectValidator, parameters); + } + + /** + * Returns the model manager + * @returns {*} the model manager associated with this Concerto class + */ + getModelManager() { + return this.modelManager; + } + + /** + * Returns true if the input object is a Concerto object + * @param {*} obj the input object + * @return {boolean} true if the object has a $class attribute + */ + isObject(obj) { + return typeof obj === 'object' && obj.$class; + } + + /** + * Returns the ClassDeclaration for an object, or throws an exception + * @param {*} obj the input object + * @throw {Error} an error if the object does not have a $class attribute + * @return {*} the ClassDeclaration for the type + */ + getTypeDeclaration(obj) { + if (!obj.$class) { + throw new Error('Input object does not have a $class attribute.'); + } + + const typeDeclaration = this.modelManager.getType(obj.$class); + + if (!typeDeclaration) { + throw new Error(`Type ${obj.$class} is not declared in the model manager`); + } + + return typeDeclaration; + } + + /** + * Gets the identifier for an object + * @param {*} obj the input object + * @return {string} The identifier for this object + */ + getIdentifier(obj) { + const typeDeclaration = this.getTypeDeclaration(obj); + const idField = typeDeclaration.getIdentifierFieldName(); + if (!idField) { + throw new Error(`Object does not have an identifier: ${JSON.stringify(obj)}`); + } + return obj[idField]; + } + + /** + * Returns true if the object has an identifier + * @param {*} obj the input object + * @return {boolean} is the object has been defined with an identifier in the model + */ + isIdentifiable(obj) { + const typeDeclaration = this.getTypeDeclaration(obj); + return typeDeclaration.getIdentifierFieldName() !== null; + } + + /** + * Returns true if the object is a relationship. Relationships are strings + * of the form: 'resource:org.accordproject.Order#001' (a relationship) + * to the 'Order' identifiable, with the id 001. + * @param {*} obj the input object + * @return {boolean} true if the object is a relationship + */ + isRelationship(obj) { + return typeof obj === 'string' && obj.startsWith(`${RESOURCE_SCHEME}:`); + } + + /** + * Set the identifier for an object. This method does *not* mutate the + * input object, use the return object. + * @param {*} obj the input object + * @param {string} id the new identifier + * @returns {*} the input object with the identifier set + */ + setIdentifier(obj, id) { + const typeDeclaration = this.getTypeDeclaration(obj); + const idField = typeDeclaration.getIdentifierFieldName(); + const clone = JSON.parse(JSON.stringify(obj)); + clone[idField] = id; + return clone; + } + + /** + * Returns the fully qualified identifier for an object + * @param {*} obj the input object + * @returns {string} the fully qualified identifier + */ + getFullyQualifiedIdentifier(obj) { + this.getTypeDeclaration(obj); + return `${obj.$class}#${this.getIdentifier(obj)}`; + } + + /** + * Returns a URI for an object + * @param {*} obj the input object + * @return {string} the URI for the object + */ + toURI(obj) { + this.getTypeDeclaration(obj); + return `${RESOURCE_SCHEME}:${obj.$class}#${encodeURI(this.getIdentifier(obj))}`; + } + + /** + * Parses a resource URI into typeDeclaration and id components. + * + * @param {string} uri the input URI + * @returns {*} an object with typeDeclaration and id attributes + * @throws {Error} if the URI is invalid or the type does not exist + * in the model manager + */ + fromURI(uri) { + let uriComponents; + try { + uriComponents = URIJS.parse(uri); + } catch (err) { + throw new Error('Invalid URI: ' + uri); + } + + const scheme = uriComponents.protocol; + if (scheme && scheme !== RESOURCE_SCHEME) { + throw new Error('Invalid URI scheme: ' + uri); + } + if (uriComponents.username || uriComponents.password || uriComponents.port || uriComponents.query) { + throw new Error('Invalid resource URI format: ' + uri); + } + + return { + typeDeclaration: this.getTypeDeclaration({ + $class: uriComponents.path + }), + id: decodeURIComponent(uriComponents.fragment) + }; + } + + /** + * Returns the short type name + * @param {*} obj the input object + * @returns {string} the short type name + */ + getType(obj) { + return this.getTypeDeclaration(obj).getName(); + } + + /** + * Returns the namespace for the object + * @param {*} obj the input object + * @returns {string} the namespace + */ + getNamespace(obj) { + return this.getTypeDeclaration(obj).getNamespace(); + } + + /** + * Check to see if this instance is an instance of the specified fully qualified + * type name. + * @param {*} obj the input object + * @param {String} fqt The fully qualified type name. + * @returns {boolean} True if this instance is an instance of the specified fully + * qualified type name, false otherwise. + */ + instanceOf(obj, fqt) { + // Check to see if this is an exact instance of the specified type. + const classDeclaration = this.getTypeDeclaration(obj); + if (classDeclaration.getFullyQualifiedName() === fqt) { + return true; + } + // Now walk the class hierachy looking to see if it's an instance of the specified type. + let superTypeDeclaration = classDeclaration.getSuperTypeDeclaration(); + while (superTypeDeclaration) { + if (superTypeDeclaration.getFullyQualifiedName() === fqt) { + return true; + } + superTypeDeclaration = superTypeDeclaration.getSuperTypeDeclaration(); + } + return false; + } +} + +module.exports = Concerto; diff --git a/packages/concerto-core/lib/factory.js b/packages/concerto-core/lib/factory.js index 680f14a73b..a7748e9dc8 100644 --- a/packages/concerto-core/lib/factory.js +++ b/packages/concerto-core/lib/factory.js @@ -27,8 +27,6 @@ const TypedStack = require('./serializer/typedstack'); const Relationship = require('./model/relationship'); const Resource = require('./model/resource'); const ValidatedResource = require('./model/validatedresource'); -const Concept = require('./model/concept'); -const ValidatedConcept = require('./model/validatedconcept'); const TransactionDeclaration = require('./introspect/transactiondeclaration'); const EventDeclaration = require('./introspect/eventdeclaration'); @@ -78,37 +76,40 @@ class Factory { const method = 'newResource'; options = options || {}; - if(typeof(id) !== 'string') { - let formatter = Globalize.messageFormatter('factory-newinstance-invalididentifier'); + const qualifiedName = ModelUtil.getFullyQualifiedName(ns, type); + const classDecl = this.modelManager.getType(qualifiedName); + + if(classDecl.isAbstract()) { + let formatter = Globalize.messageFormatter('factory-newinstance-abstracttype'); throw new Error(formatter({ namespace: ns, type: type })); } - if(!(options.allowEmptyId && id==='')) { - if(id.trim().length === 0) { - let formatter = Globalize.messageFormatter('factory-newinstance-missingidentifier'); + let idField = classDecl.getIdentifierFieldName(); + // console.log(classDecl); + if (idField) { + id = id === null || id === undefined ? uuid.v4() : id; + if(typeof(id) !== 'string') { + let formatter = Globalize.messageFormatter('factory-newinstance-invalididentifier'); throw new Error(formatter({ namespace: ns, type: type })); } - } - - const qualifiedName = ModelUtil.getFullyQualifiedName(ns, type); - const classDecl = this.modelManager.getType(qualifiedName); - if(classDecl.isAbstract()) { - let formatter = Globalize.messageFormatter('factory-newinstance-abstracttype'); - throw new Error(formatter({ - namespace: ns, - type: type - })); - } - - if(classDecl.isConcept()) { - throw new Error('Use newConcept to create concepts ' + classDecl.getFullyQualifiedName()); + if(!(options.allowEmptyId && id==='')) { + if(id.trim().length === 0) { + let formatter = Globalize.messageFormatter('factory-newinstance-missingidentifier'); + throw new Error(formatter({ + namespace: ns, + type: type + })); + } + } + } else if(id) { + throw new Error('Type is not identifiable ' + classDecl.getFullyQualifiedName()); } let newObj = null; @@ -121,10 +122,11 @@ class Factory { newObj.assignFieldDefaults(); this.initializeNewObject(newObj, classDecl, options); - // if we have an identifier, we set it now - let idField = classDecl.getIdentifierFieldName(); - newObj[idField] = id; - debug(method, 'Factory.newResource created', id ); + if (idField) { + // if we have an identifier, we set it now + newObj[idField] = id; + } + debug(method, 'Factory.newResource created ', id || 'valid'); return newObj; } @@ -144,35 +146,7 @@ class Factory { * @throws {TypeNotFoundException} if the type is not registered with the ModelManager */ newConcept(ns, type, options) { - const method = 'newConcept'; - const qualifiedName = ModelUtil.getFullyQualifiedName(ns, type); - const classDecl = this.modelManager.getType(qualifiedName); - - if(classDecl.isAbstract()) { - let formatter = Globalize.messageFormatter('factory-newinstance-abstracttype'); - throw new Error(formatter({ - namespace: ns, - type: type - })); - } - - if(!classDecl.isConcept()) { - throw new Error('Class is not a concept ' + classDecl.getFullyQualifiedName()); - } - - let newObj = null; - options = options || {}; - if(options.disableValidation) { - newObj = new Concept(this.modelManager, classDecl, ns, type); - } - else { - newObj = new ValidatedConcept(this.modelManager, classDecl, ns, type, new ResourceValidator()); - } - newObj.assignFieldDefaults(); - this.initializeNewObject(newObj, classDecl, options); - - debug(method, 'created concept', classDecl.getFullyQualifiedName() ); - return newObj; + return this.newResource(ns, type, null, options); } /** @@ -192,12 +166,14 @@ class Factory { // Load the type declaration to force an error if it doesn't exist const fqn = ModelUtil.getFullyQualifiedName(ns, type); const classDecl = this.modelManager.getType(fqn); + if(!classDecl.getIdentifierFieldName()) { + throw new Error(`Cannot create a relationship to ${fqn}, it is not identifiable.`); + } return new Relationship(this.modelManager, classDecl, ns, type, id); } /** - * Create a new transaction object. The identifier of the transaction is - * set to a UUID. + * Create a new transaction object. The identifier of the transaction is set to a UUID. * @param {String} ns - the namespace of the transaction. * @param {String} type - the type of the transaction. * @param {String} [id] - an optional identifier for the transaction; if you do not specify @@ -218,7 +194,6 @@ class Factory { } else if (!type) { throw new Error('type not specified'); } - id = id || uuid.v4(); let transaction = this.newResource(ns, type, id, options); const classDeclaration = transaction.getClassDeclaration(); @@ -255,7 +230,6 @@ class Factory { } else if (!type) { throw new Error('type not specified'); } - id = id || 'valid'; let event = this.newResource(ns, type, id, options); const classDeclaration = event.getClassDeclaration(); diff --git a/packages/concerto-core/lib/introspect/assetdeclaration.js b/packages/concerto-core/lib/introspect/assetdeclaration.js index cc457a27b7..ddf3dea998 100644 --- a/packages/concerto-core/lib/introspect/assetdeclaration.js +++ b/packages/concerto-core/lib/introspect/assetdeclaration.js @@ -14,7 +14,7 @@ 'use strict'; -const ClassDeclaration = require('./classdeclaration'); +const IdentifiedDeclaration = require('./identifieddeclaration'); /** * AssetDeclaration defines the schema (aka model or class) for @@ -27,7 +27,7 @@ const ClassDeclaration = require('./classdeclaration'); * @class * @memberof module:concerto-core */ -class AssetDeclaration extends ClassDeclaration { +class AssetDeclaration extends IdentifiedDeclaration { /** * Create an AssetDeclaration. @@ -40,25 +40,6 @@ class AssetDeclaration extends ClassDeclaration { this._isAssetDeclaration = true; } - /** - * Returns true if this class can be pointed to by a relationship - * - * @return {boolean} true if the class may be pointed to by a relationship - */ - isRelationshipTarget() { - return true; - } - - /** - * Returns the base system type for Assets from the system namespace - * - * @return {string} the short name of the base system type - */ - getSystemType() { - let systemType = this.modelFile.getModelManager().getSystemModelTable().get('Asset'); - return systemType !== undefined ? systemType : null; - } - /** * Alternative instanceof that is reliable across different module instances * @see https://github.com/hyperledger/composer-concerto/issues/47 diff --git a/packages/concerto-core/lib/introspect/classdeclaration.js b/packages/concerto-core/lib/introspect/classdeclaration.js index bbcc07564c..acd6bb7b4d 100644 --- a/packages/concerto-core/lib/introspect/classdeclaration.js +++ b/packages/concerto-core/lib/introspect/classdeclaration.js @@ -48,8 +48,6 @@ class ClassDeclaration extends Decorated { constructor(modelFile, ast) { super(modelFile, ast); this.process(); - this.fqn = ModelUtil.getFullyQualifiedName(this.modelFile.getNamespace(), this.name); - this._isClassDeclaration = true; } /** @@ -75,21 +73,26 @@ class ClassDeclaration extends Decorated { if (this.ast.classExtension) { this.superType = this.ast.classExtension.class.name; - } else { - // if we are not a system type, then we should set the - // super type to the system type for this class declaration - if (!this.isSystemCoreType()) { - this.superType = this.getSystemType(); - } + } + else if(!(this.modelFile.getNamespace() === 'concerto' && this.name === 'Concept')) { + this.superType = 'Concept'; } if (this.ast.idField) { this.idField = this.ast.idField.name; } + if(this.idField === '$identifier') { + this.addIdentifierField(); + } + for (let n = 0; n < this.ast.body.declarations.length; n++) { let thing = this.ast.body.declarations[n]; + if(thing.id && thing.id.name && thing.id.name.startsWith('$')) { + throw new IllegalModelException(`Invalid field name ${thing.id.name}`, this.modelFile, this.ast.location); + } + if (thing.type === 'FieldDeclaration') { this.properties.push(new Field(this, thing)); } else if (thing.type === 'RelationshipDeclaration') { @@ -103,16 +106,20 @@ class ClassDeclaration extends Decorated { }), this.modelFile, this.ast.location); } } + + this.fqn = ModelUtil.getFullyQualifiedName(this.modelFile.getNamespace(), this.name); + this._isClassDeclaration = true; } /** - * Adds a required field named 'timestamp' of type 'DateTime' if this class declaration does not have a super type. + * Adds a required field named 'timestamp' of type 'DateTime' if this class declaration has the 'concerto.Concept' + * super type. * This method should only be called by system code. * @private */ addTimestampField() { // add a timestamp field - if(this.superType === null) { + if(this.superType === 'Concept') { const definition = {}; definition.id = {}; definition.id.name = 'timestamp'; @@ -122,6 +129,20 @@ class ClassDeclaration extends Decorated { } } + /** + * Adds a required field named '$identifier' of type 'String' + * This method should only be called by system code. + * @private + */ + addIdentifierField() { + const definition = {}; + definition.id = {}; + definition.id.name = '$identifier'; + definition.propertyType = {}; + definition.propertyType.name = 'String'; + this.properties.push(new Field(this, definition)); + } + /** * Resolve the super type on this class and store it as an internal property. * @return {ClassDeclaration} The super type, or null if non specified. @@ -144,11 +165,10 @@ class ClassDeclaration extends Decorated { throw new IllegalModelException('Could not find super type ' + this.superType, this.modelFile, this.ast.location); } - // Prevent extending declaration with different type of declaration - if (this.constructor.name !== classDecl.constructor.name) { - let typeName = this.getSystemType(); - let superTypeName = classDecl.getSystemType(); - throw new IllegalModelException(`${typeName} (${this.getName()}) cannot extend ${superTypeName} (${classDecl.getName()})`, this.modelFile, this.ast.location); + // if super type is not a concept, then check that this type and the super type + // are of the same type. E.g. an asset cannot extend a participant + if (classDecl.constructor.name !== 'ConceptDeclaration' && this.constructor.name !== classDecl.constructor.name) { + throw new IllegalModelException(`${this.constructor.name} (${this.getName()}) cannot extend ${classDecl.constructor.name} (${classDecl.getName()})`, this.modelFile, this.ast.location); } this.superTypeDeclaration = classDecl; return classDecl; @@ -179,9 +199,6 @@ class ClassDeclaration extends Decorated { } } - // TODO (LG) check that all imported classes exist, rather than just - // used imports - // if we have a super type make sure it exists if (this.superType !== null) { this._resolveSuperType(); @@ -208,26 +225,22 @@ class ClassDeclaration extends Decorated { if (idField.isOptional()) { throw new IllegalModelException('Identifying fields cannot be optional.', this.modelFile, this.ast.location); } - if (this.getSuperType()) { - // check this class doesn't declare the identifying field as a property. - if (idField.getName() === this.getModelFile().getType(this.superType).getIdentifierFieldName()) { - throw new IllegalModelException('Identifier from super class cannot be redeclared.', this.modelFile, this.ast.location); - } - // TODO: This has been disabled pending major version bump and/or confirmation that this is illegal - // As this class has an idField declared, check the superclass doesn't - //if (this.getModelFile().getType(this.superType).getIdentifierFieldName()) { - // throw new IllegalModelException('Identifier defined in super class, identifiers cannot be overridden', this.modelFile, this.ast.location); - //} - } - } - } else { - if (this.isAbstract() === false && this.isEnum() === false && this.isConcept() === false) { - if (this.getIdentifierFieldName() === null) { - let formatter = Globalize('en').messageFormatter('classdeclaration-validate-missingidentifier'); - throw new IllegalModelException(formatter({ - 'class': this.name - }), this.modelFile, this.ast.location); + if(this.superType) { + const superType = this.getModelFile().getType(this.superType); + if (superType && superType.getIdentifierFieldName() ) { + if(this.isSystemIdentified()) { + // check that the super type is also system identified + if(!superType.isSystemIdentified()) { + throw new IllegalModelException(`Super class ${superType.getFullyQualifiedName()} has an explicit identifier ${superType.getIdentifierFieldName()} that cannot be redeclared.`, this.modelFile, this.ast.location); + } + } + else { + if(superType.isExplicitlyIdentified()) { + throw new IllegalModelException(`Super class ${superType.getFullyQualifiedName()} has an explicit identifier ${superType.getIdentifierFieldName()} that cannot be redeclared.`, this.modelFile, this.ast.location); + } + } + } } } } @@ -262,16 +275,6 @@ class ClassDeclaration extends Decorated { } } - /** - * Returns the base system type for this type of class declaration. Override - * this method in derived classes to specify a base system type. - * - * @return {string} the short name of the base system type or null - */ - getSystemType() { - return null; - } - /** * Returns true if this class is declared as abstract in the model file * @@ -308,45 +311,6 @@ class ClassDeclaration extends Decorated { return false; } - /** - * Returns true if this class can be pointed to by a relationship - * - * @return {boolean} true if the class may be pointed to by a relationship - */ - isRelationshipTarget() { - return false; - } - - /** - * Returns true if this class can be pointed to by a relationship in a - * system model - * - * @return {boolean} true if the class may be pointed to by a relationship - */ - isSystemRelationshipTarget() { - return this.isRelationshipTarget(); - } - - /** - * Returns true is this type is in the system namespace - * - * @return {boolean} true if the class may be pointed to by a relationship - */ - isSystemType() { - return this.modelFile.isSystemModelFile(); - } - - /** - * Returns true if this class is a system core type - both in the system - * namespace, and also one of the system core types (Asset, Participant, etc). - * - * @return {boolean} true if the class may be pointed to by a relationship - */ - isSystemCoreType() { - return this.isSystemType() && - this.getSystemType() === this.getName(); - } - /** * Returns the short name of a class. This name does not include the * namespace from the owning ModelFile. @@ -375,6 +339,32 @@ class ClassDeclaration extends Decorated { return this.fqn; } + /** + * Returns true if this class declaration declares an identifying field + * (system or explicit) + * @returns {Boolean} true if the class declaration includes an identifier + */ + isIdentified() { + return this.idField !== null; + } + + /** + * Returns true if this class declaration declares a system identifier + * $identifier + * @returns {Boolean} true if the class declaration includes a system identifier + */ + isSystemIdentified() { + return this.idField === '$identifier'; + } + + /** + * Returns true if this class declaration declares an explicit identifier + * @returns {Boolean} true if the class declaration includes an explicit identifier + */ + isExplicitlyIdentified() { + return this.idField && this.idField !== '$identifier'; + } + /** * Returns the name of the identifying field for this class. Note * that the identifying field may come from a super type. @@ -554,7 +544,7 @@ class ClassDeclaration extends Decorated { classDecl = this.getModelFile().getType(this.superType); } - if (classDecl === null) { + if (!classDecl) { throw new IllegalModelException('Could not find super type ' + this.superType, this.modelFile, this.ast.location); } diff --git a/packages/concerto-core/lib/introspect/conceptdeclaration.js b/packages/concerto-core/lib/introspect/conceptdeclaration.js index ba83749350..b381aaabad 100644 --- a/packages/concerto-core/lib/introspect/conceptdeclaration.js +++ b/packages/concerto-core/lib/introspect/conceptdeclaration.js @@ -30,7 +30,7 @@ const ClassDeclaration = require('./classdeclaration'); class ConceptDeclaration extends ClassDeclaration { /** - * Create an AssetDeclaration. + * Create a ConceptDeclaration. * @param {ModelFile} modelFile the ModelFile for this class * @param {Object} ast - The AST created by the parser * @throws {IllegalModelException} diff --git a/packages/concerto-core/lib/introspect/eventdeclaration.js b/packages/concerto-core/lib/introspect/eventdeclaration.js index 38b0fa8759..26c62bc164 100644 --- a/packages/concerto-core/lib/introspect/eventdeclaration.js +++ b/packages/concerto-core/lib/introspect/eventdeclaration.js @@ -14,7 +14,7 @@ 'use strict'; -const ClassDeclaration = require('./classdeclaration'); +const IdentifiedDeclaration = require('./identifieddeclaration'); /** Class representing the definition of an Event. * @extends ClassDeclaration @@ -22,7 +22,7 @@ const ClassDeclaration = require('./classdeclaration'); * @class * @memberof module:concerto-core */ -class EventDeclaration extends ClassDeclaration { +class EventDeclaration extends IdentifiedDeclaration { /** * Create an EventDeclaration. * @param {ModelFile} modelFile the ModelFile for this class @@ -45,16 +45,6 @@ class EventDeclaration extends ClassDeclaration { this.addTimestampField(); } - /** - * Returns the base system type for Events from the system namespace - * - * @return {string} the short name of the base system type - */ - getSystemType() { - let systemType = this.modelFile.getModelManager().getSystemModelTable().get('Event'); - return systemType !== undefined ? systemType : null; - } - /** * Returns true if this class is the definition of an event * diff --git a/packages/concerto-core/lib/introspect/identifieddeclaration.js b/packages/concerto-core/lib/introspect/identifieddeclaration.js new file mode 100644 index 0000000000..a1ec6e4d7a --- /dev/null +++ b/packages/concerto-core/lib/introspect/identifieddeclaration.js @@ -0,0 +1,69 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const ClassDeclaration = require('./classdeclaration'); + +/** + * IdentifiedDeclaration + * + * @extends ClassDeclaration + * @see See {@link ClassDeclaration} + * @class + * @memberof module:concerto-core + * @abstract + */ +class IdentifiedDeclaration extends ClassDeclaration { + + /** + * Create an AssetDeclaration. + * @param {ModelFile} modelFile the ModelFile for this class + * @param {Object} ast - The AST created by the parser + * @throws {IllegalModelException} + */ + constructor(modelFile, ast) { + super(modelFile, ast); + this._isIdentifiedDeclaration = true; + this.process(); + } + + /** + * Process the AST and build the model + * + * @throws {IllegalModelException} + * @private + */ + process() { + super.process(); + + if(this.superType === 'Concept' && !this.idField) { + this.idField = '$identifier'; + this.addIdentifierField(); + } + } + + /** + * Alternative instanceof that is reliable across different module instances + * @see https://github.com/hyperledger/composer-concerto/issues/47 + * + * @param {object} object - The object to test against + * @returns {boolean} - True, if the object is an instance of a AssetDeclaration + */ + static [Symbol.hasInstance](object){ + return typeof object !== 'undefined' && object !== null && Boolean(object._isIdentifiedDeclaration); + } +} + +module.exports = IdentifiedDeclaration; diff --git a/packages/concerto-core/lib/introspect/modelfile.js b/packages/concerto-core/lib/introspect/modelfile.js index b8d74dfed8..006aaa4286 100644 --- a/packages/concerto-core/lib/introspect/modelfile.js +++ b/packages/concerto-core/lib/introspect/modelfile.js @@ -42,10 +42,9 @@ class ModelFile { * ModelFile * @param {string} definitions - The DSL model as a string. * @param {string} [fileName] - The optional filename for this modelfile - * @param {boolean} [isSystemModelFile] - If true, this is a system model file, defaults to false * @throws {IllegalModelException} */ - constructor(modelManager, definitions, fileName, isSystemModelFile = false) { + constructor(modelManager, definitions, fileName) { this.modelManager = modelManager; this.external = false; this.declarations = []; @@ -84,7 +83,10 @@ class ModelFile { } this.namespace = this.ast.namespace; - this.systemModelFile = isSystemModelFile; + + if(this.namespace !== 'concerto' && this.ast.imports) { + this.ast.imports.push( { namespace: 'concerto.Concept'} ); + } if(this.ast.imports) { this.ast.imports.forEach((imp) => { @@ -100,16 +102,6 @@ class ModelFile { }); } - // if we are not in the system namespace we add imports to all the system types - if(!this.isSystemModelFile()) { - const systemTypes = this.modelManager.getSystemTypes(); - for(let index in systemTypes) { - let fqn = systemTypes[index].getFullyQualifiedName(); - this.imports.unshift(fqn); - this.importShortNames.set(ModelUtil.getShortName(fqn), fqn); - } - } - for(let n=0; n < this.ast.body.length; n++ ) { let thing = this.ast.body[n]; @@ -148,6 +140,14 @@ class ModelFile { } } + /** + * Returns true if the ModelFile is a system namespace + * @returns {Boolean} true if this is a system model file + */ + isSystemModelFile() { + return this.namespace === 'concerto'; + } + /** * Returns true if this ModelFile was downloaded from an external URI. * @return {boolean} true iff this ModelFile was downloaded from an external URI @@ -217,7 +217,6 @@ class ModelFile { * @private */ validate() { - // Validate all of the imports to check that they reference // namespaces or types that actually exist. this.imports.forEach((importName) => { @@ -293,7 +292,6 @@ class ModelFile { */ isLocalType(type) { let result = (type && this.getLocalType(type) !== null); - //console.log('isLocalType ' + this.getNamespace() + ' ' + type + '=' + result ); return result; } @@ -573,14 +571,13 @@ class ModelFile { /** * Get the instances of a given type in this ModelFile * @param {Function} type - the type of the declaration - * @param {Boolean} includeSystemType - Include the decalarations of system type in returned data * @return {ClassDeclaration[]} the ClassDeclaration defined in the model file */ - getDeclarations(type, includeSystemType = true) { + getDeclarations(type) { let result = []; for(let n=0; n < this.declarations.length; n++) { let classDeclaration = this.declarations[n]; - if(classDeclaration instanceof type && (includeSystemType || !classDeclaration.isSystemType())) { + if(classDeclaration instanceof type) { result.push(classDeclaration); } } @@ -603,14 +600,6 @@ class ModelFile { return this.definitions; } - /** - * Returns true if this ModelFile is a system model - * @return {boolean} true of this ModelFile is a system model - */ - isSystemModelFile() { - return this.systemModelFile; - } - /** * Alternative to instanceof that is reliable across different module instances * @see https://github.com/hyperledger/composer-concerto/issues/47 diff --git a/packages/concerto-core/lib/introspect/parser.js b/packages/concerto-core/lib/introspect/parser.js index 4d268bb402..236c97e267 100644 --- a/packages/concerto-core/lib/introspect/parser.js +++ b/packages/concerto-core/lib/introspect/parser.js @@ -445,45 +445,52 @@ function peg$parse(input, options) { peg$c260 = function(idField) { return idField }, - peg$c261 = function(s) { + peg$c261 = "identified", + peg$c262 = peg$literalExpectation("identified", false), + peg$c263 = function() { + return { + name: "$identifier" + } + }, + peg$c264 = function(s) { return { type: "String", value: s.value, location: location() } }, - peg$c262 = function(n) { + peg$c265 = function(n) { return { type: "Number", value: +n, location: location() } }, - peg$c263 = function(b) { + peg$c266 = function(b) { return { type: "Boolean", value: (b == "true"), location: location() } }, - peg$c264 = "[]", - peg$c265 = peg$literalExpectation("[]", false), - peg$c266 = function(value, array) { + peg$c267 = "[]", + peg$c268 = peg$literalExpectation("[]", false), + peg$c269 = function(value, array) { return { type: "Identifier", value: Object.assign({ array: !!array }, value), location: location() } }, - peg$c267 = function(d) {return d;}, - peg$c268 = function(first, last) { + peg$c270 = function(d) {return d;}, + peg$c271 = function(first, last) { return { type: "DecoratorArguments", list: first.concat(last), location: location() }; }, - peg$c269 = function(name, decoratorArgs) { + peg$c272 = function(name, decoratorArgs) { return { type: "Decorator", name: name, @@ -491,9 +498,9 @@ function peg$parse(input, options) { location: location() }; }, - peg$c270 = "{", - peg$c271 = peg$literalExpectation("{", false), - peg$c272 = function(decorators, abstract, id, idField, classExtension, body) { + peg$c273 = "{", + peg$c274 = peg$literalExpectation("{", false), + peg$c275 = function(decorators, abstract, id, idField, classExtension, body) { return { type: "AssetDeclaration", id: id, @@ -505,7 +512,7 @@ function peg$parse(input, options) { location: location() }; }, - peg$c273 = function(decorators, abstract, id, idField, classExtension, body) { + peg$c276 = function(decorators, abstract, id, idField, classExtension, body) { return { type: "ParticipantDeclaration", id: id, @@ -517,15 +524,15 @@ function peg$parse(input, options) { location: location() }; }, - peg$c274 = "extends", - peg$c275 = peg$literalExpectation("extends", false), - peg$c276 = function(ex) { + peg$c277 = "extends", + peg$c278 = peg$literalExpectation("extends", false), + peg$c279 = function(ex) { return { type: "ClassExtension", class: ex }; }, - peg$c277 = function(decorators, abstract, id, idField, classExtension, body) { + peg$c280 = function(decorators, abstract, id, idField, classExtension, body) { return { type: "TransactionDeclaration", id: id, @@ -537,7 +544,7 @@ function peg$parse(input, options) { location: location() }; }, - peg$c278 = function(decorators, abstract, id, idField, classExtension, body) { + peg$c281 = function(decorators, abstract, id, idField, classExtension, body) { return { type: "EventDeclaration", id: id, @@ -549,45 +556,46 @@ function peg$parse(input, options) { location: location() }; }, - peg$c279 = function(decorators, abstract, id, classExtension, body) { + peg$c282 = function(decorators, abstract, id, idField, classExtension, body) { return { type: "ConceptDeclaration", id: id, classExtension: classExtension, body: body, + idField: idField, abstract: abstract, decorators: decorators, location: location() }; }, - peg$c280 = "optional", - peg$c281 = peg$literalExpectation("optional", false), - peg$c282 = function() { + peg$c283 = "optional", + peg$c284 = peg$literalExpectation("optional", false), + peg$c285 = function() { return { type: "Optional" }; }, - peg$c283 = "default", - peg$c284 = peg$literalExpectation("default", false), - peg$c285 = function(def) { + peg$c286 = "default", + peg$c287 = peg$literalExpectation("default", false), + peg$c288 = function(def) { return def.value; }, - peg$c286 = function(def) { + peg$c289 = function(def) { return def; }, - peg$c287 = function(def) { + peg$c290 = function(def) { return def; }, - peg$c288 = function(decls) { + peg$c291 = function(decls) { return { type: "ClassDeclarationBody", declarations: optionalList(decls), location: location() }; }, - peg$c289 = "o", - peg$c290 = peg$literalExpectation("o", false), - peg$c291 = function(decorators, propertyType, array, id, d, optional) { + peg$c292 = "o", + peg$c293 = peg$literalExpectation("o", false), + peg$c294 = function(decorators, propertyType, array, id, d, optional) { return { type: "FieldDeclaration", id: id, @@ -599,7 +607,7 @@ function peg$parse(input, options) { location: location() } }, - peg$c292 = function(decorators, array, id, d, optional) { + peg$c295 = function(decorators, array, id, d, optional) { return { type: "FieldDeclaration", id: id, @@ -611,7 +619,7 @@ function peg$parse(input, options) { location: location() } }, - peg$c293 = function(decorators, array, id, d, optional) { + peg$c296 = function(decorators, array, id, d, optional) { return { type: "FieldDeclaration", id: id, @@ -623,7 +631,7 @@ function peg$parse(input, options) { location: location() } }, - peg$c294 = function(decorators, array, id, d, regex, optional) { + peg$c297 = function(decorators, array, id, d, regex, optional) { return { type: "FieldDeclaration", id: id, @@ -636,20 +644,20 @@ function peg$parse(input, options) { location: location() } }, - peg$c295 = "regex", - peg$c296 = peg$literalExpectation("regex", false), - peg$c297 = function(regex) { + peg$c298 = "regex", + peg$c299 = peg$literalExpectation("regex", false), + peg$c300 = function(regex) { return regex }, - peg$c298 = "range", - peg$c299 = peg$literalExpectation("range", false), - peg$c300 = function(lower, upper) { + peg$c301 = "range", + peg$c302 = peg$literalExpectation("range", false), + peg$c303 = function(lower, upper) { return { lower: lower, upper: upper } }, - peg$c301 = function(decorators, propertyType, array, id, d, range, optional) { + peg$c304 = function(decorators, propertyType, array, id, d, range, optional) { return { type: "FieldDeclaration", id: id, @@ -662,7 +670,7 @@ function peg$parse(input, options) { location: location() } }, - peg$c302 = function(decorators, id, body) { + peg$c305 = function(decorators, id, body) { return { type: "EnumDeclaration", id: id, @@ -671,13 +679,13 @@ function peg$parse(input, options) { location: location() }; }, - peg$c303 = function(decls) { + peg$c306 = function(decls) { return { type: "EnumDeclarationBody", declarations: optionalList(decls) }; }, - peg$c304 = function(decorators, id, optional) { + peg$c307 = function(decorators, id, optional) { return { type: "EnumPropertyDeclaration", id: id, @@ -686,9 +694,9 @@ function peg$parse(input, options) { location: location() } }, - peg$c305 = "-->", - peg$c306 = peg$literalExpectation("-->", false), - peg$c307 = function(decorators, propertyType, array, id, optional) { + peg$c308 = "-->", + peg$c309 = peg$literalExpectation("-->", false), + peg$c310 = function(decorators, propertyType, array, id, optional) { return { type: "RelationshipDeclaration", id: id, @@ -699,26 +707,26 @@ function peg$parse(input, options) { location: location() } }, - peg$c308 = function(first, rest) { + peg$c311 = function(first, rest) { return first.concat(JSON.stringify(rest).replace(/['"]+/g, '')); }, - peg$c309 = function(namespace) { + peg$c312 = function(namespace) { return namespace; }, - peg$c310 = ".*", - peg$c311 = peg$literalExpectation(".*", false), - peg$c312 = function(ns) { + peg$c313 = ".*", + peg$c314 = peg$literalExpectation(".*", false), + peg$c315 = function(ns) { return { namespace: ns } }, - peg$c313 = function(ns, u) { + peg$c316 = function(ns, u) { return { namespace: ns, uri: u } }, - peg$c314 = function(ns, imports, body) { + peg$c317 = function(ns, imports, body) { return { type: "Program", namespace: ns, @@ -726,10 +734,10 @@ function peg$parse(input, options) { body: optionalList(body) }; }, - peg$c315 = function(first, rest) { + peg$c318 = function(first, rest) { return buildList(first, rest, 1); }, - peg$c316 = function(first, rest) { + peg$c319 = function(first, rest) { return buildList(first, rest, 1); }, @@ -7271,6 +7279,37 @@ function peg$parse(input, options) { return s0; } + function peg$parseIdentified() { + var s0, s1; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 10) === peg$c261) { + s1 = peg$c261; + peg$currPos += 10; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c262); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c263(); + } + s0 = s1; + + return s0; + } + + function peg$parseIdentifierDeclaration() { + var s0; + + s0 = peg$parseIdentifiedByField(); + if (s0 === peg$FAILED) { + s0 = peg$parseIdentified(); + } + + return s0; + } + function peg$parseDecoratorString() { var s0, s1; @@ -7278,7 +7317,7 @@ function peg$parse(input, options) { s1 = peg$parseStringLiteral(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c261(s1); + s1 = peg$c264(s1); } s0 = s1; @@ -7292,7 +7331,7 @@ function peg$parse(input, options) { s1 = peg$parseSignedNumber(); if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c262(s1); + s1 = peg$c265(s1); } s0 = s1; @@ -7312,7 +7351,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c263(s1); + s1 = peg$c266(s1); } s0 = s1; @@ -7327,19 +7366,19 @@ function peg$parse(input, options) { if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c264) { - s3 = peg$c264; + if (input.substr(peg$currPos, 2) === peg$c267) { + s3 = peg$c267; peg$currPos += 2; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c265); } + if (peg$silentFails === 0) { peg$fail(peg$c268); } } if (s3 === peg$FAILED) { s3 = null; } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c266(s1, s3); + s1 = peg$c269(s1, s3); s0 = s1; } else { peg$currPos = s0; @@ -7405,7 +7444,7 @@ function peg$parse(input, options) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { peg$savedPos = s4; - s5 = peg$c267(s5); + s5 = peg$c270(s5); s4 = s5; } else { peg$currPos = s4; @@ -7441,7 +7480,7 @@ function peg$parse(input, options) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { peg$savedPos = s4; - s5 = peg$c267(s5); + s5 = peg$c270(s5); s4 = s5; } else { peg$currPos = s4; @@ -7477,7 +7516,7 @@ function peg$parse(input, options) { } if (s6 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c268(s3, s4); + s1 = peg$c271(s3, s4); s0 = s1; } else { peg$currPos = s0; @@ -7533,7 +7572,7 @@ function peg$parse(input, options) { } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c269(s2, s3); + s1 = peg$c272(s2, s3); s0 = s1; } else { peg$currPos = s0; @@ -7561,7 +7600,7 @@ function peg$parse(input, options) { s3 = peg$parse__(); if (s3 !== peg$FAILED) { peg$savedPos = s1; - s2 = peg$c267(s2); + s2 = peg$c270(s2); s1 = s2; } else { peg$currPos = s1; @@ -7579,7 +7618,7 @@ function peg$parse(input, options) { s3 = peg$parse__(); if (s3 !== peg$FAILED) { peg$savedPos = s1; - s2 = peg$c267(s2); + s2 = peg$c270(s2); s1 = s2; } else { peg$currPos = s1; @@ -7617,7 +7656,7 @@ function peg$parse(input, options) { if (s7 !== peg$FAILED) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { - s9 = peg$parseIdentifiedByField(); + s9 = peg$parseIdentifierDeclaration(); if (s9 === peg$FAILED) { s9 = null; } @@ -7632,11 +7671,11 @@ function peg$parse(input, options) { s12 = peg$parse__(); if (s12 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { - s13 = peg$c270; + s13 = peg$c273; peg$currPos++; } else { s13 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c271); } + if (peg$silentFails === 0) { peg$fail(peg$c274); } } if (s13 !== peg$FAILED) { s14 = peg$parse__(); @@ -7654,7 +7693,7 @@ function peg$parse(input, options) { } if (s17 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c272(s1, s3, s7, s9, s11, s15); + s1 = peg$c275(s1, s3, s7, s9, s11, s15); s0 = s1; } else { peg$currPos = s0; @@ -7751,7 +7790,7 @@ function peg$parse(input, options) { if (s7 !== peg$FAILED) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { - s9 = peg$parseIdentifiedByField(); + s9 = peg$parseIdentifierDeclaration(); if (s9 === peg$FAILED) { s9 = null; } @@ -7766,11 +7805,11 @@ function peg$parse(input, options) { s12 = peg$parse__(); if (s12 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { - s13 = peg$c270; + s13 = peg$c273; peg$currPos++; } else { s13 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c271); } + if (peg$silentFails === 0) { peg$fail(peg$c274); } } if (s13 !== peg$FAILED) { s14 = peg$parse__(); @@ -7788,7 +7827,7 @@ function peg$parse(input, options) { } if (s17 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c273(s1, s3, s7, s9, s11, s15); + s1 = peg$c276(s1, s3, s7, s9, s11, s15); s0 = s1; } else { peg$currPos = s0; @@ -7866,12 +7905,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3; s0 = peg$currPos; - if (input.substr(peg$currPos, 7) === peg$c274) { - s1 = peg$c274; + if (input.substr(peg$currPos, 7) === peg$c277) { + s1 = peg$c277; peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c275); } + if (peg$silentFails === 0) { peg$fail(peg$c278); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); @@ -7879,7 +7918,7 @@ function peg$parse(input, options) { s3 = peg$parseIdentifier(); if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c276(s3); + s1 = peg$c279(s3); s0 = s1; } else { peg$currPos = s0; @@ -7920,7 +7959,7 @@ function peg$parse(input, options) { if (s7 !== peg$FAILED) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { - s9 = peg$parseIdentifiedByField(); + s9 = peg$parseIdentifierDeclaration(); if (s9 === peg$FAILED) { s9 = null; } @@ -7935,11 +7974,11 @@ function peg$parse(input, options) { s12 = peg$parse__(); if (s12 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { - s13 = peg$c270; + s13 = peg$c273; peg$currPos++; } else { s13 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c271); } + if (peg$silentFails === 0) { peg$fail(peg$c274); } } if (s13 !== peg$FAILED) { s14 = peg$parse__(); @@ -7957,7 +7996,7 @@ function peg$parse(input, options) { } if (s17 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c277(s1, s3, s7, s9, s11, s15); + s1 = peg$c280(s1, s3, s7, s9, s11, s15); s0 = s1; } else { peg$currPos = s0; @@ -8054,7 +8093,7 @@ function peg$parse(input, options) { if (s7 !== peg$FAILED) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { - s9 = peg$parseIdentifiedByField(); + s9 = peg$parseIdentifierDeclaration(); if (s9 === peg$FAILED) { s9 = null; } @@ -8069,11 +8108,11 @@ function peg$parse(input, options) { s12 = peg$parse__(); if (s12 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { - s13 = peg$c270; + s13 = peg$c273; peg$currPos++; } else { s13 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c271); } + if (peg$silentFails === 0) { peg$fail(peg$c274); } } if (s13 !== peg$FAILED) { s14 = peg$parse__(); @@ -8091,7 +8130,7 @@ function peg$parse(input, options) { } if (s17 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c278(s1, s3, s7, s9, s11, s15); + s1 = peg$c281(s1, s3, s7, s9, s11, s15); s0 = s1; } else { peg$currPos = s0; @@ -8166,7 +8205,7 @@ function peg$parse(input, options) { } function peg$parseConceptDeclaration() { - var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15; + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17; s0 = peg$currPos; s1 = peg$parseDecorators(); @@ -8188,38 +8227,53 @@ function peg$parse(input, options) { if (s7 !== peg$FAILED) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { - s9 = peg$parseClassExtension(); + s9 = peg$parseIdentifierDeclaration(); if (s9 === peg$FAILED) { s9 = null; } if (s9 !== peg$FAILED) { s10 = peg$parse__(); if (s10 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 123) { - s11 = peg$c270; - peg$currPos++; - } else { - s11 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c271); } + s11 = peg$parseClassExtension(); + if (s11 === peg$FAILED) { + s11 = null; } if (s11 !== peg$FAILED) { s12 = peg$parse__(); if (s12 !== peg$FAILED) { - s13 = peg$parseClassDeclarationBody(); + if (input.charCodeAt(peg$currPos) === 123) { + s13 = peg$c273; + peg$currPos++; + } else { + s13 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c274); } + } if (s13 !== peg$FAILED) { s14 = peg$parse__(); if (s14 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 125) { - s15 = peg$c152; - peg$currPos++; - } else { - s15 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c153); } - } + s15 = peg$parseClassDeclarationBody(); if (s15 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c279(s1, s3, s7, s9, s13); - s0 = s1; + s16 = peg$parse__(); + if (s16 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 125) { + s17 = peg$c152; + peg$currPos++; + } else { + s17 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c153); } + } + if (s17 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c282(s1, s3, s7, s9, s11, s15); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { peg$currPos = s0; s0 = peg$FAILED; @@ -8288,16 +8342,16 @@ function peg$parse(input, options) { var s0, s1; s0 = peg$currPos; - if (input.substr(peg$currPos, 8) === peg$c280) { - s1 = peg$c280; + if (input.substr(peg$currPos, 8) === peg$c283) { + s1 = peg$c283; peg$currPos += 8; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c281); } + if (peg$silentFails === 0) { peg$fail(peg$c284); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c282(); + s1 = peg$c285(); } s0 = s1; @@ -8308,12 +8362,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5; s0 = peg$currPos; - if (input.substr(peg$currPos, 7) === peg$c283) { - s1 = peg$c283; + if (input.substr(peg$currPos, 7) === peg$c286) { + s1 = peg$c286; peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c284); } + if (peg$silentFails === 0) { peg$fail(peg$c287); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); @@ -8331,7 +8385,7 @@ function peg$parse(input, options) { s5 = peg$parseStringLiteral(); if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c285(s5); + s1 = peg$c288(s5); s0 = s1; } else { peg$currPos = s0; @@ -8361,12 +8415,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5, s6; s0 = peg$currPos; - if (input.substr(peg$currPos, 7) === peg$c283) { - s1 = peg$c283; + if (input.substr(peg$currPos, 7) === peg$c286) { + s1 = peg$c286; peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c284); } + if (peg$silentFails === 0) { peg$fail(peg$c287); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); @@ -8390,7 +8444,7 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c286(s5); + s1 = peg$c289(s5); s0 = s1; } else { peg$currPos = s0; @@ -8420,12 +8474,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5, s6; s0 = peg$currPos; - if (input.substr(peg$currPos, 7) === peg$c283) { - s1 = peg$c283; + if (input.substr(peg$currPos, 7) === peg$c286) { + s1 = peg$c286; peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c284); } + if (peg$silentFails === 0) { peg$fail(peg$c287); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); @@ -8449,7 +8503,7 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c287(s5); + s1 = peg$c290(s5); s0 = s1; } else { peg$currPos = s0; @@ -8479,12 +8533,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5, s6; s0 = peg$currPos; - if (input.substr(peg$currPos, 7) === peg$c283) { - s1 = peg$c283; + if (input.substr(peg$currPos, 7) === peg$c286) { + s1 = peg$c286; peg$currPos += 7; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c284); } + if (peg$silentFails === 0) { peg$fail(peg$c287); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); @@ -8508,7 +8562,7 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c286(s5); + s1 = peg$c289(s5); s0 = s1; } else { peg$currPos = s0; @@ -8572,7 +8626,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c288(s1); + s1 = peg$c291(s1); } s0 = s1; @@ -8588,11 +8642,11 @@ function peg$parse(input, options) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 111) { - s3 = peg$c289; + s3 = peg$c292; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c290); } + if (peg$silentFails === 0) { peg$fail(peg$c293); } } if (s3 !== peg$FAILED) { s4 = peg$parse__(); @@ -8601,12 +8655,12 @@ function peg$parse(input, options) { if (s5 !== peg$FAILED) { s6 = peg$parse__(); if (s6 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c264) { - s7 = peg$c264; + if (input.substr(peg$currPos, 2) === peg$c267) { + s7 = peg$c267; peg$currPos += 2; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c265); } + if (peg$silentFails === 0) { peg$fail(peg$c268); } } if (s7 === peg$FAILED) { s7 = null; @@ -8633,7 +8687,7 @@ function peg$parse(input, options) { s14 = peg$parse__(); if (s14 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c291(s1, s5, s7, s9, s11, s13); + s1 = peg$c294(s1, s5, s7, s9, s11, s13); s0 = s1; } else { peg$currPos = s0; @@ -8704,11 +8758,11 @@ function peg$parse(input, options) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 111) { - s3 = peg$c289; + s3 = peg$c292; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c290); } + if (peg$silentFails === 0) { peg$fail(peg$c293); } } if (s3 !== peg$FAILED) { s4 = peg$parse__(); @@ -8717,12 +8771,12 @@ function peg$parse(input, options) { if (s5 !== peg$FAILED) { s6 = peg$parse__(); if (s6 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c264) { - s7 = peg$c264; + if (input.substr(peg$currPos, 2) === peg$c267) { + s7 = peg$c267; peg$currPos += 2; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c265); } + if (peg$silentFails === 0) { peg$fail(peg$c268); } } if (s7 === peg$FAILED) { s7 = null; @@ -8749,7 +8803,7 @@ function peg$parse(input, options) { s14 = peg$parse__(); if (s14 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c292(s1, s7, s9, s11, s13); + s1 = peg$c295(s1, s7, s9, s11, s13); s0 = s1; } else { peg$currPos = s0; @@ -8820,11 +8874,11 @@ function peg$parse(input, options) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 111) { - s3 = peg$c289; + s3 = peg$c292; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c290); } + if (peg$silentFails === 0) { peg$fail(peg$c293); } } if (s3 !== peg$FAILED) { s4 = peg$parse__(); @@ -8833,12 +8887,12 @@ function peg$parse(input, options) { if (s5 !== peg$FAILED) { s6 = peg$parse__(); if (s6 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c264) { - s7 = peg$c264; + if (input.substr(peg$currPos, 2) === peg$c267) { + s7 = peg$c267; peg$currPos += 2; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c265); } + if (peg$silentFails === 0) { peg$fail(peg$c268); } } if (s7 === peg$FAILED) { s7 = null; @@ -8865,7 +8919,7 @@ function peg$parse(input, options) { s14 = peg$parse__(); if (s14 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c293(s1, s7, s9, s11, s13); + s1 = peg$c296(s1, s7, s9, s11, s13); s0 = s1; } else { peg$currPos = s0; @@ -8936,11 +8990,11 @@ function peg$parse(input, options) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 111) { - s3 = peg$c289; + s3 = peg$c292; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c290); } + if (peg$silentFails === 0) { peg$fail(peg$c293); } } if (s3 !== peg$FAILED) { s4 = peg$parse__(); @@ -8949,12 +9003,12 @@ function peg$parse(input, options) { if (s5 !== peg$FAILED) { s6 = peg$parse__(); if (s6 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c264) { - s7 = peg$c264; + if (input.substr(peg$currPos, 2) === peg$c267) { + s7 = peg$c267; peg$currPos += 2; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c265); } + if (peg$silentFails === 0) { peg$fail(peg$c268); } } if (s7 === peg$FAILED) { s7 = null; @@ -8988,7 +9042,7 @@ function peg$parse(input, options) { s16 = peg$parse__(); if (s16 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c294(s1, s7, s9, s11, s13, s15); + s1 = peg$c297(s1, s7, s9, s11, s13, s15); s0 = s1; } else { peg$currPos = s0; @@ -9062,12 +9116,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5, s6; s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c295) { - s1 = peg$c295; + if (input.substr(peg$currPos, 5) === peg$c298) { + s1 = peg$c298; peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c296); } + if (peg$silentFails === 0) { peg$fail(peg$c299); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); @@ -9091,7 +9145,7 @@ function peg$parse(input, options) { } if (s5 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c297(s5); + s1 = peg$c300(s5); s0 = s1; } else { peg$currPos = s0; @@ -9121,12 +9175,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13; s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c298) { - s1 = peg$c298; + if (input.substr(peg$currPos, 5) === peg$c301) { + s1 = peg$c301; peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c299); } + if (peg$silentFails === 0) { peg$fail(peg$c302); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); @@ -9196,7 +9250,7 @@ function peg$parse(input, options) { } if (s13 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c300(s7, s11); + s1 = peg$c303(s7, s11); s0 = s1; } else { peg$currPos = s0; @@ -9258,12 +9312,12 @@ function peg$parse(input, options) { var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13; s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c298) { - s1 = peg$c298; + if (input.substr(peg$currPos, 5) === peg$c301) { + s1 = peg$c301; peg$currPos += 5; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c299); } + if (peg$silentFails === 0) { peg$fail(peg$c302); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); @@ -9333,7 +9387,7 @@ function peg$parse(input, options) { } if (s13 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c300(s7, s11); + s1 = peg$c303(s7, s11); s0 = s1; } else { peg$currPos = s0; @@ -9400,11 +9454,11 @@ function peg$parse(input, options) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 111) { - s3 = peg$c289; + s3 = peg$c292; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c290); } + if (peg$silentFails === 0) { peg$fail(peg$c293); } } if (s3 !== peg$FAILED) { s4 = peg$parse__(); @@ -9413,12 +9467,12 @@ function peg$parse(input, options) { if (s5 !== peg$FAILED) { s6 = peg$parse__(); if (s6 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c264) { - s7 = peg$c264; + if (input.substr(peg$currPos, 2) === peg$c267) { + s7 = peg$c267; peg$currPos += 2; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c265); } + if (peg$silentFails === 0) { peg$fail(peg$c268); } } if (s7 === peg$FAILED) { s7 = null; @@ -9452,7 +9506,7 @@ function peg$parse(input, options) { s16 = peg$parse__(); if (s16 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c301(s1, s5, s7, s9, s11, s13, s15); + s1 = peg$c304(s1, s5, s7, s9, s11, s13, s15); s0 = s1; } else { peg$currPos = s0; @@ -9531,11 +9585,11 @@ function peg$parse(input, options) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 111) { - s3 = peg$c289; + s3 = peg$c292; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c290); } + if (peg$silentFails === 0) { peg$fail(peg$c293); } } if (s3 !== peg$FAILED) { s4 = peg$parse__(); @@ -9544,12 +9598,12 @@ function peg$parse(input, options) { if (s5 !== peg$FAILED) { s6 = peg$parse__(); if (s6 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c264) { - s7 = peg$c264; + if (input.substr(peg$currPos, 2) === peg$c267) { + s7 = peg$c267; peg$currPos += 2; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c265); } + if (peg$silentFails === 0) { peg$fail(peg$c268); } } if (s7 === peg$FAILED) { s7 = null; @@ -9583,7 +9637,7 @@ function peg$parse(input, options) { s16 = peg$parse__(); if (s16 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c301(s1, s5, s7, s9, s11, s13, s15); + s1 = peg$c304(s1, s5, s7, s9, s11, s13, s15); s0 = s1; } else { peg$currPos = s0; @@ -9670,11 +9724,11 @@ function peg$parse(input, options) { s6 = peg$parse__(); if (s6 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { - s7 = peg$c270; + s7 = peg$c273; peg$currPos++; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c271); } + if (peg$silentFails === 0) { peg$fail(peg$c274); } } if (s7 !== peg$FAILED) { s8 = peg$parse__(); @@ -9692,7 +9746,7 @@ function peg$parse(input, options) { } if (s11 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c302(s1, s5, s9); + s1 = peg$c305(s1, s5, s9); s0 = s1; } else { peg$currPos = s0; @@ -9754,7 +9808,7 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c303(s1); + s1 = peg$c306(s1); } s0 = s1; @@ -9770,11 +9824,11 @@ function peg$parse(input, options) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 111) { - s3 = peg$c289; + s3 = peg$c292; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c290); } + if (peg$silentFails === 0) { peg$fail(peg$c293); } } if (s3 !== peg$FAILED) { s4 = peg$parse__(); @@ -9791,7 +9845,7 @@ function peg$parse(input, options) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c304(s1, s5, s7); + s1 = peg$c307(s1, s5, s7); s0 = s1; } else { peg$currPos = s0; @@ -9837,12 +9891,12 @@ function peg$parse(input, options) { if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { - if (input.substr(peg$currPos, 3) === peg$c305) { - s3 = peg$c305; + if (input.substr(peg$currPos, 3) === peg$c308) { + s3 = peg$c308; peg$currPos += 3; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c306); } + if (peg$silentFails === 0) { peg$fail(peg$c309); } } if (s3 !== peg$FAILED) { s4 = peg$parse__(); @@ -9851,12 +9905,12 @@ function peg$parse(input, options) { if (s5 !== peg$FAILED) { s6 = peg$parse__(); if (s6 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c264) { - s7 = peg$c264; + if (input.substr(peg$currPos, 2) === peg$c267) { + s7 = peg$c267; peg$currPos += 2; } else { s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c265); } + if (peg$silentFails === 0) { peg$fail(peg$c268); } } if (s7 === peg$FAILED) { s7 = null; @@ -9876,7 +9930,7 @@ function peg$parse(input, options) { s12 = peg$parse__(); if (s12 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c307(s1, s5, s7, s9, s11); + s1 = peg$c310(s1, s5, s7, s9, s11); s0 = s1; } else { peg$currPos = s0; @@ -9996,7 +10050,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c308(s1, s2); + s1 = peg$c311(s1, s2); s0 = s1; } else { peg$currPos = s0; @@ -10023,7 +10077,7 @@ function peg$parse(input, options) { s4 = peg$parse__(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c309(s3); + s1 = peg$c312(s3); s0 = s1; } else { peg$currPos = s0; @@ -10057,12 +10111,12 @@ function peg$parse(input, options) { s4 = peg$currPos; s5 = peg$parseQualifiedName(); if (s5 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c310) { - s6 = peg$c310; + if (input.substr(peg$currPos, 2) === peg$c313) { + s6 = peg$c313; peg$currPos += 2; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c311); } + if (peg$silentFails === 0) { peg$fail(peg$c314); } } if (s6 === peg$FAILED) { s6 = null; @@ -10087,7 +10141,7 @@ function peg$parse(input, options) { s4 = peg$parse__(); if (s4 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c312(s3); + s1 = peg$c315(s3); s0 = s1; } else { peg$currPos = s0; @@ -10121,12 +10175,12 @@ function peg$parse(input, options) { s4 = peg$currPos; s5 = peg$parseQualifiedName(); if (s5 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c310) { - s6 = peg$c310; + if (input.substr(peg$currPos, 2) === peg$c313) { + s6 = peg$c313; peg$currPos += 2; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c311); } + if (peg$silentFails === 0) { peg$fail(peg$c314); } } if (s6 === peg$FAILED) { s6 = null; @@ -10165,7 +10219,7 @@ function peg$parse(input, options) { s8 = peg$parse__(); if (s8 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c313(s3, s7); + s1 = peg$c316(s3, s7); s0 = s1; } else { peg$currPos = s0; @@ -10231,7 +10285,7 @@ function peg$parse(input, options) { } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c314(s1, s2, s3); + s1 = peg$c317(s1, s2, s3); s0 = s1; } else { peg$currPos = s0; @@ -10291,7 +10345,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c315(s1, s2); + s1 = peg$c318(s1, s2); s0 = s1; } else { peg$currPos = s0; @@ -10347,7 +10401,7 @@ function peg$parse(input, options) { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c316(s1, s2); + s1 = peg$c319(s1, s2); s0 = s1; } else { peg$currPos = s0; diff --git a/packages/concerto-core/lib/introspect/parser.pegjs b/packages/concerto-core/lib/introspect/parser.pegjs index 5e4bca1dc3..8090f46497 100644 --- a/packages/concerto-core/lib/introspect/parser.pegjs +++ b/packages/concerto-core/lib/introspect/parser.pegjs @@ -767,6 +767,17 @@ IdentifiedByField return idField } +Identified + = "identified" { + return { + name: "$identifier" + } + } + +IdentifierDeclaration + = IdentifiedByField / + Identified + DecoratorString = s:StringLiteral { return { @@ -833,7 +844,7 @@ Decorators = decorators:(d:Decorator __ {return d;})* AssetDeclaration - = decorators:Decorators __ abstract:AbstractToken? __ AssetToken __ id:Identifier __ idField:IdentifiedByField? __ classExtension: ClassExtension? __ + = decorators:Decorators __ abstract:AbstractToken? __ AssetToken __ id:Identifier __ idField:IdentifierDeclaration? __ classExtension: ClassExtension? __ "{" __ body:ClassDeclarationBody __ "}" { return { @@ -849,7 +860,7 @@ AssetDeclaration } ParticipantDeclaration - = decorators:Decorators __ abstract:AbstractToken? __ ParticipantToken __ id:Identifier __ idField:IdentifiedByField? __ classExtension: ClassExtension? __ + = decorators:Decorators __ abstract:AbstractToken? __ ParticipantToken __ id:Identifier __ idField:IdentifierDeclaration? __ classExtension: ClassExtension? __ "{" __ body:ClassDeclarationBody __ "}" { return { @@ -874,7 +885,7 @@ ClassExtension } TransactionDeclaration - = decorators:Decorators __ abstract:AbstractToken? __ TransactionToken __ id:Identifier __ idField:IdentifiedByField? __ classExtension: ClassExtension? __ + = decorators:Decorators __ abstract:AbstractToken? __ TransactionToken __ id:Identifier __ idField:IdentifierDeclaration? __ classExtension: ClassExtension? __ "{" __ body:ClassDeclarationBody __ "}" { return { @@ -890,7 +901,7 @@ TransactionDeclaration } EventDeclaration - = decorators:Decorators __ abstract:AbstractToken? __ EventToken __ id:Identifier __ idField:IdentifiedByField? __ classExtension: ClassExtension? __ + = decorators:Decorators __ abstract:AbstractToken? __ EventToken __ id:Identifier __ idField:IdentifierDeclaration? __ classExtension: ClassExtension? __ "{" __ body:ClassDeclarationBody __ "}" { return { @@ -906,7 +917,7 @@ EventDeclaration } ConceptDeclaration - = decorators:Decorators __ abstract:AbstractToken? __ ConceptToken __ id:Identifier __ classExtension: ClassExtension? __ + = decorators:Decorators __ abstract:AbstractToken? __ ConceptToken __ id:Identifier __ idField:IdentifierDeclaration? __ classExtension: ClassExtension? __ "{" __ body:ClassDeclarationBody __ "}" { return { @@ -914,6 +925,7 @@ ConceptDeclaration id: id, classExtension: classExtension, body: body, + idField: idField, abstract: abstract, decorators: decorators, location: location() diff --git a/packages/concerto-core/lib/introspect/participantdeclaration.js b/packages/concerto-core/lib/introspect/participantdeclaration.js index b07185dd6a..d9cb4426ed 100644 --- a/packages/concerto-core/lib/introspect/participantdeclaration.js +++ b/packages/concerto-core/lib/introspect/participantdeclaration.js @@ -14,7 +14,7 @@ 'use strict'; -const ClassDeclaration = require('./classdeclaration'); +const IdentifiedDeclaration = require('./identifieddeclaration'); /** Class representing the definition of a Participant. * @extends ClassDeclaration @@ -23,7 +23,7 @@ const ClassDeclaration = require('./classdeclaration'); * @class * @memberof module:concerto-core */ -class ParticipantDeclaration extends ClassDeclaration { +class ParticipantDeclaration extends IdentifiedDeclaration { /** * Create an ParticipantDeclaration. * @param {ModelFile} modelFile the ModelFile for this class @@ -35,25 +35,6 @@ class ParticipantDeclaration extends ClassDeclaration { this._isParticipantDeclaration = true; } - /** - * Returns true if this class can be pointed to by a relationship - * - * @return {boolean} true if the class may be pointed to by a relationship - */ - isRelationshipTarget() { - return true; - } - - /** - * Returns the base system type for Participants from the system namespace - * - * @return {string} the short name of the base system type - */ - getSystemType() { - let systemType = this.modelFile.getModelManager().getSystemModelTable().get('Participant'); - return systemType !== undefined ? systemType : null; - } - /** * Alternative instanceof that is reliable across different module instances * @see https://github.com/hyperledger/composer-concerto/issues/47 diff --git a/packages/concerto-core/lib/introspect/relationshipdeclaration.js b/packages/concerto-core/lib/introspect/relationshipdeclaration.js index 8428bebb5d..1e9b510df7 100644 --- a/packages/concerto-core/lib/introspect/relationshipdeclaration.js +++ b/packages/concerto-core/lib/introspect/relationshipdeclaration.js @@ -78,10 +78,10 @@ class RelationshipDeclaration extends Property { throw new IllegalModelException('Relationship ' + this.getName() + ' points to a missing type ' + this.getFullyQualifiedTypeName(), classDecl.getModelFile(), this.ast.location); } - if (classDecl.getModelFile().isSystemModelFile()) { - // Transaction relationship in event, continue - } else if(classDeclaration.isRelationshipTarget() === false) { - throw new IllegalModelException('Relationship ' + this.getName() + ' must be to an asset or participant, but is to ' + this.getFullyQualifiedTypeName(), classDecl.getModelFile(), this.ast.location); + if (classDeclaration.getIdentifierFieldName()) { + // Relationship to a class with an identifier continue + } else { + throw new IllegalModelException('Relationship ' + this.getName() + ' must be to a class that has an identifier, but this is to ' + this.getFullyQualifiedTypeName(), classDecl.getModelFile(), this.ast.location); } } } diff --git a/packages/concerto-core/lib/introspect/transactiondeclaration.js b/packages/concerto-core/lib/introspect/transactiondeclaration.js index 7386a4257b..0000c7556d 100644 --- a/packages/concerto-core/lib/introspect/transactiondeclaration.js +++ b/packages/concerto-core/lib/introspect/transactiondeclaration.js @@ -14,7 +14,7 @@ 'use strict'; -const ClassDeclaration = require('./classdeclaration'); +const IdentifiedDeclaration = require('./identifieddeclaration'); /** Class representing the definition of an Transaction. * @extends ClassDeclaration @@ -23,7 +23,7 @@ const ClassDeclaration = require('./classdeclaration'); * @class * @memberof module:concerto-core */ -class TransactionDeclaration extends ClassDeclaration { +class TransactionDeclaration extends IdentifiedDeclaration { /** * Create an TransactionDeclaration. * @param {ModelFile} modelFile the ModelFile for this class @@ -46,16 +46,6 @@ class TransactionDeclaration extends ClassDeclaration { this.addTimestampField(); } - /** - * Returns the base system type for Transactions from the system namespace - * - * @return {string} the short name of the base system type - */ - getSystemType() { - let systemType = this.modelFile.getModelManager().getSystemModelTable().get('Transaction'); - return systemType !== undefined ? systemType : null; - } - /** * Alternative instanceof that is reliable across different module instances * @see https://github.com/hyperledger/composer-concerto/issues/47 diff --git a/packages/concerto-core/lib/logger.js b/packages/concerto-core/lib/logger.js index ca256a0b49..6f45832437 100644 --- a/packages/concerto-core/lib/logger.js +++ b/packages/concerto-core/lib/logger.js @@ -14,128 +14,241 @@ 'use strict'; -const winston = require('winston'); -const { - LEVEL, - MESSAGE -} = require('triple-beam'); -const jsonStringify = require('fast-safe-stringify'); +/* eslint-disable no-console */ +/* eslint-disable no-use-before-define */ + +const colors = require('colors/safe'); const jsome = require('jsome'); -const fs = require('fs'); -const env = process.env.NODE_ENV || 'development'; -const logsFolder = process.env.CONCERTO_LOG_FOLDER_PATH || ''; -const path = require('path'); -const tsFormat = () => (new Date()).toLocaleTimeString(); + +jsome.params.lintable = true; /** - * Helper function to test is a string is a stringified version of a JSON object - * @param {string} str - the input string to test - * @returns {boolean} - true iff the string can be parsed as JSON - * @private + * Default levels for the npm configuration. + * @type {Object} */ -function isJSON(str) { +const levels = { + error: 0, + warn: 1, + info: 2, + http: 3, + verbose: 4, + debug: 5, + silly: 6 +}; + +/** + * Default levels for the npm configuration. + * @type {Object} + */ +const colorMap = { + error: 'red', + warn: 'yellow', + info: 'green', + verbose: 'cyan', + debug: 'blue', + silly: 'magenta' +}; + +const timestamp = () => (new Date()).toLocaleTimeString(); +const colorize = level => colors[colorMap[level]](level.toUpperCase()); + +/** +* Helper function to test if a string is a stringified version of a JSON object +* @param {string} str - the input string to test +* @returns {boolean} - true iff the string can be parsed as JSON +* @private +*/ +const isJson = (str) => { try { return (JSON.parse(str) && !!str); } catch (e) { return false; } -} - -jsome.params.lintable = true; - -const jsonColor = winston.format(info => { - const padding = info.padding && info.padding[info.level] || ''; +}; - if (info[LEVEL] === 'error' && info.stack) { - info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding} ${info.message}\n${info.stack}`; - return info; +/** +* Helper function to color and format JSON objects +* @param {any} obj - the input obj to prettify +* @returns {any} - the prettified object +* @private +*/ +const prettifyJson = (obj) => { + if(typeof obj === 'object') { + return `\n${jsome.getColoredString(obj, null, 2)}`; + } else if(isJson(obj)) { + return `\n${jsome.getColoredString(JSON.parse(obj), null, 2)}`; } + return obj; +}; - if (info[LEVEL] === 'info' || info[LEVEL] === 'warn') { - if (typeof info.message === 'object') { - info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding}\n${jsome.getColoredString(info.message, null, 2)}`; - } else if (isJSON(info.message)) { - info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding}\n${jsome.getColoredString(JSON.parse(info.message), null, 2)}`; - } else { - info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding} ${info.message}`; +/** +* The default transport for logging at multiple levels to the console +* @param {string} level - the required log level. e.g. error, warn, info, debug, etc. +* @param {any} obj - the input obj to prettify +* @returns {void} - +* @private +*/ +const defaultTransportShim = (level, ...args) => { + let mutatedLevel = level; + let data = args; + let first = data.shift(); + + // Flatten log object + if(first && typeof first === 'object' && first.level && first.message){ + const padding = first.padding && first.padding[first.level]; + if (first.level === 'error' && first.stack) { + mutatedLevel = 'error'; + first = `${first.message}\n${first.stack}`; + } else if (Object.keys(levels).includes(first.level)) { + mutatedLevel = first.level; + first = first.message; } - return info; + first = padding ? `${padding} ${first}` : first; } - const stringifiedRest = jsonStringify(Object.assign({}, info, { - level: undefined, - message: undefined, - splat: undefined - })); + data.unshift(first); - if (stringifiedRest !== '{}') { - info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding} ${info.message} ${stringifiedRest}`; - } else { - info[MESSAGE] = `${tsFormat()} - ${info.level}:${padding} ${info.message}`; - } - return info; + const stream = ['error', 'warn'].includes(mutatedLevel) ? console.error : console.log; + stream( + `${timestamp()} - ${colorize(mutatedLevel)}:`, + ...data + .map(obj => obj instanceof Error ? `${obj.message}\n${obj.stack}`: obj) + .map(prettifyJson) + ); +}; +const defaultTransport = {}; +Object.keys(levels).forEach(level => { + defaultTransport[level] = (...args) => defaultTransportShim(level, ...args); }); -const enumerateErrorFormat = winston.format(info => { - if (info.message instanceof Error) { - info.message = Object.assign({ - message: info.message.message, - stack: info.message.stack - }, info.message); - } +/** + * A utility class with static function that print to the console + * @private + */ +class Logger { + /** + * A reusable function for logging at multiple levels + * @param {string} level - the required log level. e.g. error, warn, info, debug, etc. + * @param {any} obj - the input obj to prettify + * @returns {void} - + * @private + */ + static dispatch(level, ...args) { + if (levels[level] > levels[this.level]){ + return; + } - if (info instanceof Error) { - return Object.assign({ - message: info.message, - stack: info.stack - }, info); + this.transports.forEach(t => { + if(t[level]){ + t[level](...args); + } + }); } - return info; -}); - -let logger = winston.createLogger({ - format: winston.format.combine( - winston.format.json(), - enumerateErrorFormat(), - winston.format.colorize(), - jsonColor(), - ), - transports: [ - new winston.transports.Console({ - level: 'info', - }), - ] -}); - -// Only write log files to disk if we're running in development -// and not in a browser (webpack or browserify) -const setupLogger = ((process, env, logDir) => { - if (env === 'development' && !process.browser) { - // Create the log directory if it does not exist + /** + * Add a custom transport for logging + * @param {Object} transport - The transport object should have function for the usual logging operations e.g. error, warn, info, debug, etc. + * @returns {void} - + * @private + */ + static add(transport) { + this.transports.push(transport); + } - try { - if (!fs.existsSync(logDir)) { - fs.mkdirSync(logDir); - } + /** + * Write an error statement to the console. + * + * Prints to `stderr` with newline. + * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first + * @param {any} args - + * @returns {void} - + * @private + */ + static error(...args){ return this.dispatch('error', ...args); } + + /** + * Write a warning statement to the console. + * + * Prints to `stderr` with newline. + * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first + * @param {any} args - + * @returns {void} - + * @private + */ + static warn(...args){ return this.dispatch('warn', ...args); } + + /** + * Write an info statement to the console. + * + * Prints to `stdout` with newline. + * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first + * @param {any} args - + * @returns {void} - + * @private + */ + static info(...args){ return this.dispatch('info', ...args); } + + /** + * Write an info statement to the console. Alias for `logger.log` + * + * Prints to `stdout` with newline. + * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first + * @param {any} args - + * @returns {void} - + * @private + */ + static log(...args){ return this.info(...args); } + + /** + * Write an http statement to the console. + * + * Prints to `stdout` with newline. + * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first + * @param {any} args - + * @returns {void} - + * @private + */ + static http(...args){ return this.dispatch('http', ...args); } + + /** + * Write a verbose log statement to the console. + * + * Prints to `stdout` with newline. + * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first + * @param {any} args - + * @returns {void} - + * @private + */ + static verbose(...args){ return this.dispatch('verbose', ...args); } + + /** + * Write a debug statement to the console. + * + * Prints to `stdout` with newline. + * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first + * @param {any} args - + * @returns {void} - + * @private + */ + static debug(...args){ return this.dispatch('debug', ...args); } + + /** + * Write a silly level statement to the console. + * + * Prints to `stdout` with newline. + * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first + * @param {any} args - + * @returns {void} - + * @private + */ + static silly(...args){ return this.dispatch('silly', ...args); } +} - logger.add(new winston.transports.File({ - name: 'logs-file', - filename: `${logDir}/trace.log`, - level: 'debug' - })); - } - catch(error) { - console.log('Failed to create log directory. File logging disabled.'); - } - } -}); +// Set the default logging level +Logger.level = 'info'; -const logDir = logsFolder ? path.normalize(logsFolder + '/log') : 'log'; -setupLogger(process, env, logDir); -logger.setup = setupLogger; -logger.entry = logger.debug; -logger.exit = logger.debug; +// A list of user-provided logging tranports +Logger.transports = [ defaultTransport ]; -module.exports = logger; +module.exports = Logger; diff --git a/packages/concerto-core/lib/model/concept.js b/packages/concerto-core/lib/model/concept.js deleted file mode 100644 index 0357066632..0000000000 --- a/packages/concerto-core/lib/model/concept.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -'use strict'; - -const Typed = require('./typed'); - -/** - * Resource is an instance that has a type. The type of the resource - * specifies a set of properites (which themselves have types). - * - * - * Type information in Concerto is used to validate the structure of - * Resource instances and for serialization. - * - * - * Resources are used in Concerto to represent Assets, Participants, Transactions and - * other domain classes that can be serialized for long-term persistent storage. - * - * @extends Typed - * @see See {@link Resource} - * @class - * @memberof module:concerto-core - */ -class Concept extends Typed { - /** - * This constructor should not be called directly. - *

- * Note: Only to be called by framework code. Applications should - * retrieve instances from {@link Factory} - *

- * - * @param {ModelManager} modelManager - The ModelManager for this instance - * @param {ClassDeclaration} classDeclaration - The class declaration for this instance. - * @param {string} ns - The namespace this instance. - * @param {string} type - The type this instance. - * @private - */ - constructor(modelManager, classDeclaration, ns, type) { - super(modelManager, classDeclaration, ns, type); - } - - - /** - * Determine if this typed is a concept. - * @return {boolean} True if this typed is a concept, - * false if not. - */ - isConcept() { - return true; - } -} - -module.exports = Concept; diff --git a/packages/concerto-core/lib/model/resource.js b/packages/concerto-core/lib/model/resource.js index d2336c3274..d2edb6ad2f 100644 --- a/packages/concerto-core/lib/model/resource.js +++ b/packages/concerto-core/lib/model/resource.js @@ -71,6 +71,24 @@ class Resource extends Identifiable { return true; } + /** + * Determine if this identifiable is a concept. + * @return {boolean} True if this identifiable is a concept, + * false if not. + */ + isConcept() { + return this.getClassDeclaration().isConcept(); + } + + /** + * Determine if this object is identifiable. + * @return {boolean} True if this object has an identifiying field + * false if not. + */ + isIdentifiable() { + return this.getClassDeclaration().getIdentifierFieldName(); + } + /** * Serialize this resource into a JavaScript object suitable for serialization to JSON, * using the default options for the serializer. If you need to set additional options diff --git a/packages/concerto-core/lib/model/validatedconcept.js b/packages/concerto-core/lib/model/validatedconcept.js deleted file mode 100644 index 37c0a0d945..0000000000 --- a/packages/concerto-core/lib/model/validatedconcept.js +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -const Concept = require('./concept'); -const TypedStack = require('../serializer/typedstack'); - -/** - * - * Resource is an instance that has a type. The type of the resource - * specifies a set of properites (which themselves have types). - * - * - * Type information in Concerto is used to validate the structure of - * Resource instances and for serialization. - * - * - * Resources are used in Concerto to represent Assets, Participants, Transactions and - * other domain classes that can be serialized for long-term persistent storage. - * - * @extends Concept - * @see See {@link Resource} - * @class - * @memberof module:concerto-core - */ -class ValidatedConcept extends Concept { - /** - * This constructor should not be called directly. - *

- * Note: Only to be called by framework code. Applications should - * retrieve instances from {@link Factory} - *

- * - * @param {ModelManager} modelManager - The ModelManager for this instance - * @param {ClassDeclaration} classDeclaration - The class declaration for this instance. - * @param {string} ns - The namespace this instance. - * @param {string} type - The type this instance. - * @param {ResourceValidator} resourceValidator - The validator to use for this instance - * @private - */ - constructor(modelManager, classDeclaration, ns, type, resourceValidator) { - super(modelManager, classDeclaration, ns, type); - this.$validator = resourceValidator; - } - - /** - * Sets a property, validating that it does not violate the model - * @param {string} propName - the name of the field - * @param {string} value - the value of the property - * @throws {Error} if the value is not compatible with the model definition for the field - */ - setPropertyValue(propName, value) { - let classDeclaration = this.getClassDeclaration(); - let field = classDeclaration.getProperty(propName); - - if (!field) { - throw new Error('Trying to set field ' + - propName + ' which is not declared in the model.'); - } - // else { - // this.log( 'Validating field ' + field + ' with data ' + value ); - // } - - const parameters = {}; - parameters.stack = new TypedStack(value); - parameters.modelManager = this.getModelManager(); - parameters.rootResourceIdentifier = 'undefined'; - field.accept(this.$validator, parameters); - super.setPropertyValue(propName,value); - } - - /** - * Adds an array property value, validating that it does not violate the model - * @param {string} propName - the name of the field - * @param {string} value - the value of the property - * @throws {Error} if the value is not compatible with the model definition for the field - */ - addArrayValue(propName, value) { - let classDeclaration = this.getClassDeclaration(); - let field = classDeclaration.getProperty(propName); - - if (!field) { - throw new Error('Trying to set field ' + - propName + ' which is not declared in the model.'); - } - - if (!field.isArray()) { - throw new Error('Trying to add array item ' + - propName + ' which is not declared as an array in the model.'); - } - - const parameters = {}; - let newArray = []; - if(this[propName]) { - newArray = this[propName].slice(0); - } - newArray.push(value); - parameters.stack = new TypedStack(newArray); - parameters.modelManager = this.getModelManager(); - parameters.rootResourceIdentifier = 'undefined'; - field.accept(this.$validator, parameters); - super.addArrayValue(propName, value); - } - - /** - * Validates the instance against its model. - * - * @throws {Error} - if the instance if invalid with respect to the model - */ - validate() { - const classDeclaration = this.getClassDeclaration(); - const parameters = {}; - parameters.stack = new TypedStack(this); - parameters.modelManager = this.getModelManager(); - parameters.rootResourceIdentifier = 'undefined'; - classDeclaration.accept(this.$validator, parameters); - } -} - -module.exports = ValidatedConcept; diff --git a/packages/concerto-core/lib/modelloader.js b/packages/concerto-core/lib/modelloader.js index 879e10e77b..77754666ef 100644 --- a/packages/concerto-core/lib/modelloader.js +++ b/packages/concerto-core/lib/modelloader.js @@ -20,17 +20,6 @@ const DefaultModelFileLoader = require('./introspect/loaders/defaultmodelfileloa const ModelFile = require('./introspect/modelfile'); const ModelManager = require('./modelmanager'); -const defaultSystemContent = `namespace org.accordproject.base -abstract asset Asset { } -abstract participant Participant { } -abstract transaction Transaction identified by transactionId { - o String transactionId -} -abstract event Event identified by eventId { - o String eventId -}`; -const defaultSystemName = '@org.accordproject.base'; - /** * Create a ModelManager from model files, with an optional system model. * @@ -46,49 +35,38 @@ class ModelLoader { * @param {object} modelFileLoader - the model loader * @param {object} modelManager - the model manager * @param {string} ctoFile - the model file - * @param {boolean} system - whether this is a system model * @return {object} the model manager * @private */ - static async addModel(modelFileLoader, modelManager, ctoFile, system) { + static async addModel(modelFileLoader, modelManager, ctoFile) { let modelFile = null; - if (system && !ctoFile) { - modelFile = new ModelFile(modelManager, defaultSystemContent, defaultSystemName, true); - } else if(modelFileLoader.accepts(ctoFile)) { + if (modelFileLoader.accepts(ctoFile)) { modelFile = await modelFileLoader.load(ctoFile); } else { const content = fs.readFileSync(ctoFile, 'utf8'); modelFile = new ModelFile(modelManager, content, ctoFile); } - if (system) { - modelManager.addModelFile(modelFile, modelFile.getName(), false, true); - } else { - modelManager.addModelFile(modelFile, modelFile.getName(), true, false); - } + modelManager.addModelFile(modelFile, modelFile.getName(), true); return modelManager; } /** - * Load system and models in a new model manager + * Load models in a new model manager * - * @param {string} ctoSystemFile - the system model file * @param {string[]} ctoFiles - the CTO files (can be local file paths or URLs) * @param {object} options - optional parameters * @param {boolean} [options.offline] - do not resolve external models * @return {object} the model manager */ - static async loadModelManager(ctoSystemFile, ctoFiles, options = { offline: false }) { + static async loadModelManager(ctoFiles, options = { offline: false }) { let modelManager = new ModelManager(); const modelFileLoader = new DefaultModelFileLoader(modelManager); - // Load system model - modelManager = await ModelLoader.addModel(modelFileLoader,modelManager,ctoSystemFile,true); - // Load user models - for( let ctoFile of ctoFiles ) { - modelManager = await ModelLoader.addModel(modelFileLoader,modelManager,ctoFile,false); + for(let ctoFile of ctoFiles) { + modelManager = await ModelLoader.addModel(modelFileLoader,modelManager,ctoFile); } // Validate the models, either offline or with external model resolution @@ -104,22 +82,17 @@ class ModelLoader { /** * Load system and models in a new model manager from model files objects * - * @param {string} ctoSystemFile - the system model file * @param {object[]} modelFiles - An array of Concerto files as strings or ModelFile objects. * @param {string[]} [fileNames] - An optional array of file names to associate with the model files * @param {object} options - optional parameters * @param {boolean} [options.offline] - do not resolve external models * @return {object} the model manager */ - static async loadModelManagerFromModelFiles(ctoSystemFile, modelFiles, fileNames, options = { offline: false }) { + static async loadModelManagerFromModelFiles(modelFiles, fileNames, options = { offline: false }) { let modelManager = new ModelManager(); - const modelFileLoader = new DefaultModelFileLoader(modelManager); // Load system model - modelManager = await ModelLoader.addModel(modelFileLoader,modelManager,ctoSystemFile,true); - - // Load user models - modelManager.addModelFiles(modelFiles, fileNames); + modelManager.addModelFiles(modelFiles, fileNames, true); // Validate the models, either offline or with external model resolution if(options && options.offline) { diff --git a/packages/concerto-core/lib/modelmanager.js b/packages/concerto-core/lib/modelmanager.js index 1b9fd42592..0dbb62b209 100644 --- a/packages/concerto-core/lib/modelmanager.js +++ b/packages/concerto-core/lib/modelmanager.js @@ -39,10 +39,9 @@ const debug = require('debug')('concerto:ModelManager'); * a set of asset, transaction and participant type definitions. * * Concerto applications load their Concerto files and then call the {@link ModelManager#addModelFile addModelFile} - * method to register the Concerto file(s) with the ModelManager. The ModelManager - * parses the text of the Concerto file and will make all defined types available - * to other Concerto services, such as the {@link Serializer} (to convert instances to/from JSON) - * and {@link Factory} (to create instances). + * method to register the Concerto file(s) with the ModelManager. + * + * Use the {@link Concerto} class to validate instances. * * @class * @memberof module:concerto-core @@ -56,8 +55,18 @@ class ModelManager { this.factory = new Factory(this); this.serializer = new Serializer(this.factory, this); this.decoratorFactories = []; - this.systemModelTable = new Map(); this._isModelManager = true; + this.addRootModel(); + } + + /** + * Adds root types + * @private + */ + addRootModel() { + this.addModelFile( `namespace concerto + concept Concept { + }`, 'concerto.cto'); } /** @@ -115,28 +124,17 @@ class ModelManager { * @param {string} modelFile - The Concerto file as a string * @param {string} fileName - an optional file name to associate with the model file * @param {boolean} [disableValidation] - If true then the model files are not validated - * @param {boolean} [systemModelTable] - A table that maps classes in the new models to system types * @throws {IllegalModelException} * @return {Object} The newly added model file (internal). */ - addModelFile(modelFile, fileName, disableValidation,systemModelTable) { + addModelFile(modelFile, fileName, disableValidation) { const NAME = 'addModelFile'; debug(NAME, 'addModelFile', modelFile, fileName); let m = null; - // Update the system model table with either the provided table or the default one - const isSystemModelFile = typeof systemModelTable !== 'undefined'; - if(isSystemModelFile) { - if(typeof systemModelTable === 'object') { - systemModelTable.forEach((key, value) => this.systemModelTable.set(key, value)); - } else { - ModelUtil.getIdentitySystemModelTable().forEach((key, value) => this.systemModelTable.set(key, value)); - } - } - if (typeof modelFile === 'string') { - m = new ModelFile(this, modelFile, fileName, systemModelTable !== undefined); + m = new ModelFile(this, modelFile, fileName); } else { m = modelFile; } @@ -153,14 +151,6 @@ class ModelManager { return m; } - /** - * @return {Map} A table that maps classes in the new models to system types - * @private - */ - getSystemModelTable() { - return this.systemModelTable; - } - /** * Updates a Concerto file (as a string) on the ModelManager. * Concerto files have a single namespace. If a Concerto file with the @@ -181,16 +171,14 @@ class ModelManager { } else { let existing = this.modelFiles[modelFile.getNamespace()]; if (!existing) { - throw new Error('model file does not exist'); - } else if (existing.isSystemModelFile()) { - throw new Error('System namespace can not be updated'); + throw new Error(`Model file for namespace ${modelFile.getNamespace()} not found`); } if (!disableValidation) { modelFile.validate(); } - this.modelFiles[modelFile.getNamespace()] = modelFile; - return modelFile; } + this.modelFiles[modelFile.getNamespace()] = modelFile; + return modelFile; } /** @@ -200,9 +188,7 @@ class ModelManager { */ deleteModelFile(namespace) { if (!this.modelFiles[namespace]) { - throw new Error('model file does not exist'); - } else if (this.modelFiles[namespace].isSystemModelFile()) { - throw new Error('Cannot delete system namespace'); + throw new Error('Model file does not exist'); } else { delete this.modelFiles[namespace]; } @@ -213,29 +199,16 @@ class ModelManager { * @param {object[]} modelFiles - An array of Concerto files as strings or ModelFile objects. * @param {string[]} [fileNames] - An optional array of file names to associate with the model files * @param {boolean} [disableValidation] - If true then the model files are not validated - * @param {boolean} [systemModelTable] - A table that maps classes in the new models to system types * @returns {Object[]} The newly added model files (internal). */ - addModelFiles(modelFiles, fileNames, disableValidation, systemModelTable) { + addModelFiles(modelFiles, fileNames, disableValidation) { const NAME = 'addModelFiles'; debug(NAME, 'addModelFiles', modelFiles, fileNames); const originalModelFiles = {}; - const originalSystemModelTable = {}; Object.assign(originalModelFiles, this.modelFiles); - Object.assign(originalSystemModelTable, this.systemModelTable); let newModelFiles = []; try { - // Update the system model table with either the provided table or the default one - const isSystemModelFile = typeof systemModelTable !== 'undefined'; - if(isSystemModelFile) { - if(typeof systemModelTable === 'object') { - systemModelTable.forEach((key, value) => this.systemModelTable.set(key, value)); - } else { - ModelUtil.getIdentitySystemModelTable().forEach((key, value) => this.systemModelTable.set(key, value)); - } - } - // create the model files for (let n = 0; n < modelFiles.length; n++) { const modelFile = modelFiles[n]; @@ -245,27 +218,12 @@ class ModelManager { fileName = fileNames[n]; } - if (typeof modelFile === 'string') { - let m = new ModelFile(this, modelFile, fileName, isSystemModelFile); - if (m.isSystemModelFile()) { - throw new Error('System namespace can not be updated'); - } - if (!this.modelFiles[m.getNamespace()]) { - this.modelFiles[m.getNamespace()] = m; - newModelFiles.push(m); - } else { - this._throwAlreadyExists(m); - } + const m = typeof modelFile === 'string' ? new ModelFile(this, modelFile, fileName) : modelFile; + if (!this.modelFiles[m.getNamespace()]) { + this.modelFiles[m.getNamespace()] = m; + newModelFiles.push(m); } else { - if (modelFile.isSystemModelFile()) { - throw new Error('System namespace can not be updated'); - } - if (!this.modelFiles[modelFile.getNamespace()]) { - this.modelFiles[modelFile.getNamespace()] = modelFile; - newModelFiles.push(modelFile); - } else { - this._throwAlreadyExists(modelFile); - } + this._throwAlreadyExists(m); } } @@ -278,9 +236,7 @@ class ModelManager { return newModelFiles; } catch (err) { this.modelFiles = {}; - this.systemModelTable = {}; Object.assign(this.modelFiles, originalModelFiles); - Object.assign(this.systemModelTable, originalSystemModelTable); throw err; } finally { debug(NAME, newModelFiles); @@ -368,8 +324,6 @@ class ModelManager { * @param {Object} [options] - Options object * @param {boolean} options.includeExternalModels - * If true, external models are written to the file system. Defaults to true - * @param {boolean} options.includeSystemModels - - * If true, system models are written to the file system. Defaults to false */ writeModelsToFileSystem(path, options = {}) { if(!path){ @@ -378,13 +332,9 @@ class ModelManager { const opts = Object.assign({ includeExternalModels: true, - includeSystemModels: false, }, options); this.getModelFiles().forEach(function (file) { - if (file.isSystemModelFile() && !opts.includeSystemModels) { - return; - } if (file.isExternal() && !opts.includeExternalModels) { return; } @@ -396,46 +346,30 @@ class ModelManager { /** * Get the array of model file instances - * Note - this is an internal method and therefore will return the system model - * as well as any network defined models. - * - * It is the callers responsibility to remove this before the data leaves an external API - * + * @param {Boolean} [includeConcertoNamespace] - whether to include the concerto namespace + * (default to false) * @return {ModelFile[]} The ModelFiles registered * @private */ - getModelFiles() { + getModelFiles(includeConcertoNamespace) { let keys = Object.keys(this.modelFiles); let result = []; for (let n = 0; n < keys.length; n++) { - result.push(this.modelFiles[keys[n]]); + const ns = keys[n]; + if(includeConcertoNamespace || ns !== 'concerto') { + result.push(this.modelFiles[ns]); + } } return result; } /** - * Get the array of system model file instances - * Note - this is an internal method and therefore will return the system model - * - * @return {ModelFile[]} The system ModelFiles registered - * @private - */ - getSystemModelFiles() { - return this.getModelFiles() - .filter((modelFile) => { - return modelFile.isSystemModelFile(); - }); - } - - /** - * Gets all the CTO models + * Gets all the Concerto models * @param {Object} [options] - Options object * @param {boolean} options.includeExternalModels - * If true, external models are written to the file system. Defaults to true - * @param {boolean} options.includeSystemModels - - * If true, system models are written to the file system. Defaults to false * @return {Array<{name:string, content:string}>} the name and content of each CTO file */ getModels(options) { @@ -443,13 +377,9 @@ class ModelManager { let models = []; const opts = Object.assign({ includeExternalModels: true, - includeSystemModels: false, }, options); modelFiles.forEach(function (file) { - if (file.isSystemModelFile() && !opts.includeSystemModels) { - return; - } if (file.isExternal() && !opts.includeExternalModels) { return; } @@ -505,23 +435,13 @@ class ModelManager { * Remove all registered Concerto files */ clearModelFiles() { - const systemModelFiles = this.getSystemModelFiles(); this.modelFiles = {}; - - systemModelFiles.forEach((m) => { - this.modelFiles[m.getNamespace()] = m; - }); - - // now validate all the models - this.validateModelFiles(); + this.addRootModel(); } /** * Get the ModelFile associated with a namespace - * Note - this is an internal method and therefore will return the system model - * as well as any network defined models. * - * It is the callers responsibility to remove this before the data leaves an external API * @param {string} namespace - the namespace containing the ModelFile * @return {ModelFile} registered ModelFile for the namespace or null * @private @@ -532,10 +452,7 @@ class ModelManager { /** * Get the ModelFile associated with a file name - * Note - this is an internal method and therefore will return the system model - * as well as any network defined models. * - * It is the callers responsibility to remove this before the data leaves an external API * @param {string} fileName - the fileName associated with the ModelFile * @return {ModelFile} registered ModelFile for the namespace or null * @private @@ -583,24 +500,6 @@ class ModelManager { return classDecl; } - - /** - * Get all class declarations from system namespaces - * @return {ClassDeclaration[]} the ClassDeclarations from system namespaces - */ - getSystemTypes() { - return this.getModelFiles() - .filter((modelFile) => { - return modelFile.isSystemModelFile(); - }) - .reduce((classDeclarations, modelFile) => { - return classDeclarations.concat(modelFile.getAllDeclarations()); - }, []) - .filter((classDeclaration) => { - return classDeclaration.isSystemCoreType(); - }); - } - /** * Get the AssetDeclarations defined in this model manager * @param {Boolean} includeSystemType - Include the decalarations of system type in returned data diff --git a/packages/concerto-core/lib/modelutil.js b/packages/concerto-core/lib/modelutil.js index d652ce91e9..c45f9f6c0e 100644 --- a/packages/concerto-core/lib/modelutil.js +++ b/packages/concerto-core/lib/modelutil.js @@ -190,29 +190,6 @@ class ModelUtil { return type; } } - - /** - * Returns the default system model table for a system model file where the class names - * exactly match the defaults expected by the ClassDeclarations. - * - * The default names are: - * - 'Transaction' - * - 'Asset' - * - 'Event' - * - 'Participant' - * - * @returns {string} the fully qualified type name. - */ - static getIdentitySystemModelTable() { - const systemModelTable = new Map(); - - systemModelTable.set('Transaction', 'Transaction'); - systemModelTable.set('Asset', 'Asset'); - systemModelTable.set('Event', 'Event'); - systemModelTable.set('Participant', 'Participant'); - - return systemModelTable; - } } module.exports = ModelUtil; diff --git a/packages/concerto-core/lib/serializer.js b/packages/concerto-core/lib/serializer.js index 27950ad975..8b915e3128 100644 --- a/packages/concerto-core/lib/serializer.js +++ b/packages/concerto-core/lib/serializer.js @@ -154,15 +154,15 @@ class Serializer { // create a new instance, using the identifier field name as the ID. let resource; if (classDeclaration instanceof TransactionDeclaration) { - resource = this.factory.newTransaction( classDeclaration.getNamespace(), + resource = this.factory.newTransaction(classDeclaration.getNamespace(), classDeclaration.getName(), jsonObject[classDeclaration.getIdentifierFieldName()] ); } else if (classDeclaration instanceof EventDeclaration) { - resource = this.factory.newEvent( classDeclaration.getNamespace(), + resource = this.factory.newEvent(classDeclaration.getNamespace(), classDeclaration.getName(), jsonObject[classDeclaration.getIdentifierFieldName()] ); } else if (classDeclaration instanceof ConceptDeclaration) { - resource = this.factory.newConcept( classDeclaration.getNamespace(), + resource = this.factory.newConcept(classDeclaration.getNamespace(), classDeclaration.getName() ); } else if (classDeclaration instanceof EnumDeclaration) { throw new Error('Attempting to create an ENUM declaration is not supported.'); diff --git a/packages/concerto-core/lib/serializer/instancegenerator.js b/packages/concerto-core/lib/serializer/instancegenerator.js index b9e873f2a8..3ad7116202 100644 --- a/packages/concerto-core/lib/serializer/instancegenerator.js +++ b/packages/concerto-core/lib/serializer/instancegenerator.js @@ -125,14 +125,26 @@ class InstanceGenerator { case 'DateTime': return parameters.valueGenerator.getDateTime(); case 'Integer': + if(field.validator){ + return parameters.valueGenerator.getRange(field.validator.lowerBound, field.validator.upperBound, type); + } return parameters.valueGenerator.getInteger(); case 'Long': + if(field.validator){ + return parameters.valueGenerator.getRange(field.validator.lowerBound, field.validator.upperBound, type); + } return parameters.valueGenerator.getLong(); case 'Double': + if(field.validator){ + return parameters.valueGenerator.getRange(field.validator.lowerBound, field.validator.upperBound, type); + } return parameters.valueGenerator.getDouble(); case 'Boolean': return parameters.valueGenerator.getBoolean(); default: + if(field.validator){ + return parameters.valueGenerator.getRegex(field.validator.regex); + } return parameters.valueGenerator.getString(); } } @@ -174,8 +186,7 @@ class InstanceGenerator { } const concreteSubclasses = declaration.getAssignableClassDeclarations() - .filter(subclass => !subclass.isAbstract()) - .filter(subclass => !subclass.isSystemType()); + .filter(subclass => !subclass.isAbstract()); if (concreteSubclasses.length === 0) { const formatter = Globalize.messageFormatter('instancegenerator-newinstance-noconcreteclass'); diff --git a/packages/concerto-core/lib/serializer/jsongenerator.js b/packages/concerto-core/lib/serializer/jsongenerator.js index 40c90c29f0..08c6c83f2f 100644 --- a/packages/concerto-core/lib/serializer/jsongenerator.js +++ b/packages/concerto-core/lib/serializer/jsongenerator.js @@ -18,9 +18,7 @@ const ClassDeclaration = require('../introspect/classdeclaration'); const Field = require('../introspect/field'); const RelationshipDeclaration = require('../introspect/relationshipdeclaration'); const Resource = require('../model/resource'); -const Identifiable = require('../model/identifiable'); const Typed = require('../model/typed'); -const Concept = require('../model/concept'); const ModelUtil = require('../modelutil'); const Util = require('../util'); @@ -86,14 +84,14 @@ class JSONGenerator { visitClassDeclaration(classDeclaration, parameters) { const obj = parameters.stack.pop(); - if (!((obj instanceof Resource) || (obj instanceof Concept))) { - throw new Error('Expected a Resource or a Concept, but found ' + obj); + if (!((obj instanceof Resource))) { + throw new Error('Expected a Resource, but found ' + obj); } let result = {}; let id = null; - if (obj instanceof Identifiable && this.deduplicateResources) { + if (obj.isIdentifiable() && this.deduplicateResources) { id = obj.toURI(); if( parameters.dedupeResources.has(id)) { return id; @@ -154,16 +152,16 @@ class JSONGenerator { const enumDeclaration = field.getParent().getModelFile().getType(field.getType()); const enumName = enumDeclaration.getFullyQualifiedName(); const properties = enumDeclaration.getProperties(); - let either = { 'left' : obj }; + let either = { '$left' : obj }; for(let n=0; n < properties.length; n++) { const property = properties[n]; if(property.getName() === obj) { break; } else { - either = { 'right' : either }; + either = { '$right' : either }; } } - result = { 'type' : [enumName], 'data': either }; + result = { '$class' : [enumName], '$data': either }; } else { result = this.convertToJSON(field, obj); } @@ -172,7 +170,15 @@ class JSONGenerator { const classDeclaration = parameters.modelManager.getType(obj.getFullyQualifiedType()); result = classDeclaration.accept(this, parameters); } - + if (field.isOptional()) { + if (this.ergo) { + if (result) { + result = { '$left' : result }; + } else { + result = { '$right' : result }; + } + } + } return result; } @@ -196,7 +202,7 @@ class JSONGenerator { case 'Integer': case 'Long': { if (this.ergo) { - return { nat: obj }; + return { $nat: obj }; } else { return obj; } diff --git a/packages/concerto-core/lib/serializer/jsonpopulator.js b/packages/concerto-core/lib/serializer/jsonpopulator.js index a5f0488483..7a8f6eaec2 100644 --- a/packages/concerto-core/lib/serializer/jsonpopulator.js +++ b/packages/concerto-core/lib/serializer/jsonpopulator.js @@ -121,10 +121,19 @@ class JSONPopulator { validateProperties(properties, classDeclaration); properties.forEach((property) => { - const value = jsonObj[property]; - parameters.jsonStack.push(value); - const classProperty = classDeclaration.getProperty(property); - resourceObj[property] = classProperty.accept(this,parameters); + let value = jsonObj[property]; + if (this.ergo) { // XXX Unpack optionals + if (Object.prototype.hasOwnProperty.call(value,'$left')) { + value = value.$left; + } else if (Object.prototype.hasOwnProperty.call(value,'$right')) { + value = value.$right; + } + } + if (value !== null) { + parameters.jsonStack.push(value); + const classProperty = classDeclaration.getProperty(property); + resourceObj[property] = classProperty.accept(this,parameters); + } }); return resourceObj; @@ -156,12 +165,12 @@ class JSONPopulator { } /** - * - * @param {Field} field - the field of the item being converted - * @param {Object} jsonItem - the JSON object of the item being converted - * @param {Object} parameters - the parameters - * @return {Object} - the populated object. - */ + * + * @param {Field} field - the field of the item being converted + * @param {Object} jsonItem - the JSON object of the item being converted + * @param {Object} parameters - the parameters + * @return {Object} - the populated object. + */ convertItem(field, jsonItem, parameters) { let result = null; @@ -214,35 +223,64 @@ class JSONPopulator { let result = null; switch(field.getType()) { - case 'DateTime': + case 'DateTime': { if (Moment.isMoment(json)) { result = json; } else { - result = new Moment.parseZone(json); + // Uses strict mode + result = new Moment.parseZone(json, Moment.ISO_8601, true); + } + if (!result.isValid()) { + throw new ValidationException(`Expected value ${JSON.stringify(json)} to be of type ${field.getType()}`); } + } break; case 'Integer': - case 'Long': - result = this.ergo ? parseInt(json.nat) : parseInt(json); + case 'Long': { + const num = this.ergo ? json.$nat : json; + if (typeof num === 'number') { + if (Math.trunc(num) !== num) { + throw new ValidationException(`Expected value ${JSON.stringify(json)} to be of type ${field.getType()}`); + } else { + result = num; + } + } else { + throw new ValidationException(`Expected value ${JSON.stringify(json)} to be of type ${field.getType()}`); + } + } break; - case 'Double': - result = parseFloat(json); + case 'Double': { + if (typeof json === 'number') { + result = parseFloat(json); + } else { + throw new ValidationException(`Expected value ${JSON.stringify(json)} to be of type ${field.getType()}`); + } + } break; - case 'Boolean': - result = (json === true || json === 'true'); + case 'Boolean': { + if (typeof json === 'boolean') { + result = json; + } else { + throw new ValidationException(`Expected value ${JSON.stringify(json)} to be of type ${field.getType()}`); + } + } break; case 'String': - result = json.toString(); + if (typeof json === 'string') { + result = json; + } else { + throw new ValidationException(`Expected value ${JSON.stringify(json)} to be of type ${field.getType()}`); + } break; default: { // everything else should be an enumerated value... if (this.ergo) { // unpack the enum - let current = json.data; - while (!current.left) { - current = current.right; + let current = json.$data; + while (!current.$left) { + current = current.$right; } - result = current.left; + result = current.$left; } else { result = json; } diff --git a/packages/concerto-core/lib/serializer/objectvalidator.js b/packages/concerto-core/lib/serializer/objectvalidator.js new file mode 100644 index 0000000000..474c37e056 --- /dev/null +++ b/packages/concerto-core/lib/serializer/objectvalidator.js @@ -0,0 +1,569 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const ClassDeclaration = require('../introspect/classdeclaration'); +const Field = require('../introspect/field'); +const RelationshipDeclaration = require('../introspect/relationshipdeclaration'); +const EnumDeclaration = require('../introspect/enumdeclaration'); +const Util = require('../util'); +const ModelUtil = require('../modelutil'); +const ValidationException = require('./validationexception'); +const Globalize = require('../globalize'); +const moment = require('moment-mini'); + +/** + *

+ * Validates a Resource or Field against the models defined in the ModelManager. + * This class is used with the Visitor pattern and visits the class declarations + * (etc) for the model, checking that the data in a Resource / Field is consistent + * with the model. + *

+ * The parameters for the visit method must contain the following properties: + * + * @private + * @class + * @memberof module:concerto-core + */ +class ObjectValidator { + + /** + * ResourceValidator constructor + * @param {*} concerto - the Concerto instance used for validation + * @param {Object} [options] - the optional validation options. + * @param {boolean} [options.validate] - validate the structure of the Resource + * with its model prior to serialization (default to true) + * @param {boolean} [options.convertResourcesToRelationships] - Convert resources that + * are specified for relationship fields into relationships, false by default. + * @param {boolean} [options.permitResourcesForRelationships] - Permit resources in the + */ + constructor(concerto, options) { + this.options = options || {}; + this.concerto = concerto; + if(!this.concerto) { + throw new Error('Missing concerto instance'); + } + } + /** + * Visitor design pattern. + * + * @param {Object} thing - the object being visited + * @param {Object} parameters - the parameter + * @return {Object} the result of visiting or null + * @private + */ + visit(thing, parameters) { + if (thing instanceof EnumDeclaration) { + return this.visitEnumDeclaration(thing, parameters); + } else if (thing instanceof ClassDeclaration) { + return this.visitClassDeclaration(thing, parameters); + } else if (thing instanceof RelationshipDeclaration) { + return this.visitRelationshipDeclaration(thing, parameters); + } else if (thing instanceof Field) { + return this.visitField(thing, parameters); + } + } + + /** + * Visitor design pattern + * + * @param {EnumDeclaration} enumDeclaration - the object being visited + * @param {Object} parameters - the parameter + * @return {Object} the result of visiting or null + * @private + */ + visitEnumDeclaration(enumDeclaration, parameters) { + const obj = parameters.stack.pop(); + + // now check that obj is one of the enum values + const properties = enumDeclaration.getProperties(); + let found = false; + for(let n=0; n < properties.length; n++) { + const property = properties[n]; + if(property.getName() === obj) { + found = true; + } + } + + if(!found) { + ObjectValidator.reportInvalidEnumValue( parameters.rootResourceIdentifier, enumDeclaration, obj ); + } + + return null; + } + + /** + * Visitor design pattern + * @param {ClassDeclaration} classDeclaration - the object being visited + * @param {Object} parameters - the parameter + * @return {Object} the result of visiting or null + * @private + */ + visitClassDeclaration(classDeclaration, parameters) { + + const obj = parameters.stack.pop(); + + if(this.concerto.isIdentifiable(obj)) { + parameters.rootResourceIdentifier = this.concerto.getFullyQualifiedIdentifier(obj); + } + + const toBeAssignedClassDeclaration = this.concerto.getModelManager().getType(obj.$class); + const toBeAssignedClassDecName = toBeAssignedClassDeclaration.getFullyQualifiedName(); + + // is the type we are assigning to abstract? + // the only way this can happen is if the type is non-abstract + // and then gets redeclared as abstract + if(toBeAssignedClassDeclaration.isAbstract()) { + ObjectValidator.reportAbstractClass(toBeAssignedClassDeclaration); + } + + // are there extra fields in the object? + let props = Object.getOwnPropertyNames(obj); + for (let n = 0; n < props.length; n++) { + let propName = props[n]; + if(!this.isSystemProperty(propName)) { + const field = toBeAssignedClassDeclaration.getProperty(propName); + if (!field) { + if(this.concerto.isIdentifiable( obj)) { + ObjectValidator.reportUndeclaredField(this.concerto.getIdentifier(obj), propName, toBeAssignedClassDecName); + } + else { + ObjectValidator.reportUndeclaredField(parameters.currentIdentifier, propName, toBeAssignedClassDecName); + } + } + } + } + + if (this.concerto.isIdentifiable( obj )) { + const id = this.concerto.getIdentifier(obj); + + // prevent empty identifiers + if(!id || id.trim().length === 0) { + ObjectValidator.reportEmptyIdentifier(parameters.rootResourceIdentifier); + } + + parameters.currentIdentifier = this.concerto.getFullyQualifiedIdentifier(obj); + } + + // now validate each property + const properties = toBeAssignedClassDeclaration.getProperties(); + for(let n=0; n < properties.length; n++) { + const property = properties[n]; + const value = obj[property.getName()]; + if(!Util.isNull(value)) { + parameters.stack.push(value); + property.accept(this,parameters); + } + else { + if(!property.isOptional()) { + ObjectValidator.reportMissingRequiredProperty( parameters.rootResourceIdentifier, property); + } + } + } + return null; + } + + /** + * Returns true if the property is a system property. + * System properties are not declared in the model. + * @param {String} propertyName - the name of the property + * @return {Boolean} true if the property is a system property + * @private + */ + isSystemProperty(propertyName) { + return propertyName.charAt(0) === '$'; + } + + /** + * Visitor design pattern + * @param {Field} field - the object being visited + * @param {Object} parameters - the parameter + * @return {Object} the result of visiting or null + * @private + */ + visitField(field, parameters) { + const obj = parameters.stack.pop(); + + let dataType = typeof(obj); + let propName = field.getName(); + + if (dataType === 'symbol') { + ObjectValidator.reportFieldTypeViolation(parameters.rootResourceIdentifier, propName, obj, field, this.concerto); + } + + if(field.isTypeEnum()) { + this.checkEnum(obj, field,parameters); + } + else { + if(field.isArray()) { + this.checkArray(obj, field,parameters); + } + else { + this.checkItem(obj, field,parameters); + } + } + + return null; + } + + /** + * Check a Field that is declared as an Array. + * @param {Object} obj - the object being validated + * @param {Field} field - the object being visited + * @param {Object} parameters - the parameter + * @private + */ + checkEnum(obj,field,parameters) { + + if(field.isArray() && !(obj instanceof Array)) { + ObjectValidator.reportFieldTypeViolation(parameters.rootResourceIdentifier, field.getName(), obj, field, this.concerto); + } + + const enumDeclaration = field.getParent().getModelFile().getType(field.getType()); + + if(field.isArray()) { + for(let n=0; n < obj.length; n++) { + const item = obj[n]; + parameters.stack.push(item); + enumDeclaration.accept(this, parameters); + } + } + else { + const item = obj; + parameters.stack.push(item); + enumDeclaration.accept(this, parameters); + } + } + + /** + * Check a Field that is declared as an Array. + * @param {Object} obj - the object being validated + * @param {Field} field - the object being visited + * @param {Object} parameters - the parameter + * @private + */ + checkArray(obj,field,parameters) { + + if(!(obj instanceof Array)) { + ObjectValidator.reportFieldTypeViolation(parameters.rootResourceIdentifier, field.getName(), obj, field, this.concerto); + } + + for(let n=0; n < obj.length; n++) { + const item = obj[n]; + this.checkItem(item, field, parameters); + } + } + + /** + * Check a single (non-array) field. + * @param {Object} obj - the object being validated + * @param {Field} field - the object being visited + * @param {Object} parameters - the parameter + * @private + */ + checkItem(obj,field, parameters) { + let dataType = typeof obj; + let propName = field.getName(); + + if (dataType === 'symbol') { + ObjectValidator.reportFieldTypeViolation(parameters.rootResourceIdentifier, propName, obj, field, this.concerto); + } + + if(field.isPrimitive()) { + let invalid = false; + + switch(field.getType()) { + case 'String': + if(dataType !== 'string') { + invalid = true; + } + break; + case 'Double': + case 'Long': + case 'Integer': + if(dataType !== 'number') { + invalid = true; + } + break; + case 'Boolean': + if(dataType !== 'boolean') { + invalid = true; + } + break; + case 'DateTime': + if(!moment(obj, moment.ISO_8601).isValid()) { + invalid = true; + } + break; + } + if (invalid) { + ObjectValidator.reportFieldTypeViolation(parameters.rootResourceIdentifier, propName, obj, field, this.concerto); + } + else { + if(field.getValidator() !== null) { + field.getValidator().validate(parameters.currentIdentifier, obj); + } + } + } + else { + // a field that points to a transaction, asset, participant... + let classDeclaration = this.concerto.getModelManager().getType(field.getFullyQualifiedTypeName()); + try { + classDeclaration = this.concerto.getModelManager().getType(obj.$class); + } catch (err) { + ObjectValidator.reportFieldTypeViolation(parameters.rootResourceIdentifier, propName, obj, field, this.concerto); + } + + // is it compatible? + if(!ModelUtil.isAssignableTo(classDeclaration.getModelFile(), classDeclaration.getFullyQualifiedName(), field)) { + ObjectValidator.reportInvalidFieldAssignment(parameters.rootResourceIdentifier, propName, obj, field); + } + + // recurse + parameters.stack.push(obj); + classDeclaration.accept(this, parameters); + } + } + + /** + * Visitor design pattern + * @param {RelationshipDeclaration} relationshipDeclaration - the object being visited + * @param {Object} parameters - the parameter + * @return {Object} the result of visiting or null + * @private + */ + visitRelationshipDeclaration(relationshipDeclaration, parameters) { + const obj = parameters.stack.pop(); + + if(relationshipDeclaration.isArray()) { + if(!(obj instanceof Array)) { + ObjectValidator.reportInvalidFieldAssignment(parameters.rootResourceIdentifier, relationshipDeclaration.getName(), obj, relationshipDeclaration); + } + + for(let n=0; n < obj.length; n++) { + const item = obj[n]; + this.checkRelationship(parameters, relationshipDeclaration, item); + } + } + else { + this.checkRelationship(parameters, relationshipDeclaration, obj); + } + return null; + } + + /** + * Check a single relationship + * @param {Object} parameters - the parameter + * @param {*} relationshipDeclaration - the object being visited + * @param {Object} obj - the object being validated + * @private + */ + checkRelationship(parameters, relationshipDeclaration, obj) { + if(this.concerto.isRelationship( obj )) { + // All good.. + } else if (this.concerto.isIdentifiable(obj) && (this.options.convertResourcesToRelationships || this.options.permitResourcesForRelationships)) { + // All good.. Again + } else { + ObjectValidator.reportNotRelationshipViolation(parameters.rootResourceIdentifier, relationshipDeclaration, obj); + } + + const relationshipType = this.concerto.isRelationship(obj) ? this.concerto.fromURI(obj).typeDeclaration + : this.concerto.getTypeDeclaration(obj); + + if(!relationshipType.getIdentifierFieldName()) { + throw new Error('Relationship can only be to identified types.'); + } + + if(!ModelUtil.isAssignableTo(relationshipType.getModelFile(), relationshipType.getFullyQualifiedName(), relationshipDeclaration)) { + ObjectValidator.reportInvalidFieldAssignment(parameters.rootResourceIdentifier, relationshipDeclaration.getName(), obj, relationshipDeclaration); + } + } + + /** + * Throw a new error for a model violation. + * @param {string} id - the identifier of this instance. + * @param {string} propName - the name of the field. + * @param {*} value - the value of the field. + * @param {Field} field - the field + * @param {*} concerto - the concerto instance + * @throws {ValidationException} the exception + * @private + */ + static reportFieldTypeViolation(id, propName, value, field, concerto) { + let isArray = field.isArray() ? '[]' : ''; + let typeOfValue = typeof value; + + if( concerto.isObject(value) && concerto.isIdentifiable(value)) { + typeOfValue = value.getFullyQualifiedType(); + value = value.getFullyQualifiedIdentifier(); + } + else { + if(value) { + try { + value = JSON.stringify(value); + } + catch(err) { + value = value.toString(); + } + } + } + + let formatter = Globalize.messageFormatter('resourcevalidator-fieldtypeviolation'); + throw new ValidationException(formatter({ + resourceId: id, + propertyName: propName, + fieldType: field.getType() + isArray, + value: value, + typeOfValue: typeOfValue + })); + } + + /** + * Throw a new error for a model violation. + * @param {string} id - the identifier of this instance. + * @param {classDeclaration} classDeclaration - the declaration of the classs + * @param {Object} value - the value of the field. + * @private + */ + static reportNotResouceViolation(id, classDeclaration, value) { + let formatter = Globalize.messageFormatter('resourcevalidator-notresourceorconcept'); + throw new ValidationException(formatter({ + resourceId: id, + classFQN: classDeclaration.getFullyQualifiedName(), + invalidValue: value.toString() + })); + } + + /** + * Throw a new error for a model violation. + * @param {string} id - the identifier of this instance. + * @param {RelationshipDeclaration} relationshipDeclaration - the declaration of the classs + * @param {Object} value - the value of the field. + * @private + */ + static reportNotRelationshipViolation(id, relationshipDeclaration, value) { + let formatter = Globalize.messageFormatter('resourcevalidator-notrelationship'); + throw new ValidationException(formatter({ + resourceId: id, + classFQN: relationshipDeclaration.getFullyQualifiedTypeName(), + invalidValue: value.toString() + })); + } + + /** + * Throw a new error for a missing, but required field. + * @param {string} id - the identifier of this instance. + * @param {Field} field - the field/ + * @private + */ + static reportMissingRequiredProperty(id, field) { + let formatter = Globalize.messageFormatter('resourcevalidator-missingrequiredproperty'); + throw new ValidationException(formatter({ + resourceId: id, + fieldName: field.getName() + })); + } + + /** + * Throw a new error for a missing, but required field. + * @param {string} id - the identifier of this instance. + * @param {Field} field - the field/ + * @private + */ + static reportEmptyIdentifier(id) { + let formatter = Globalize.messageFormatter('resourcevalidator-emptyidentifier'); + throw new ValidationException(formatter({ + resourceId: id + })); + } + + /** + * Throw a new error for a missing, but required field. + * @param {string} id - the identifier of this instance. + * @param {Field} field - the field + * @param {string} obj - the object value + * @private + */ + static reportInvalidEnumValue(id, field, obj) { + let formatter = Globalize.messageFormatter('resourcevalidator-invalidenumvalue'); + throw new ValidationException(formatter({ + resourceId: id, + value: obj, + fieldName: field.getName() + })); + } + + /** + * Throw a validation exception for an abstract class + * @param {ClassDeclaration} classDeclaration - the class declaration + * @throws {ValidationException} the validation exception + * @private + */ + static reportAbstractClass(classDeclaration) { + let formatter = Globalize.messageFormatter('resourcevalidator-abstractclass'); + throw new ValidationException(formatter({ + className: classDeclaration.getFullyQualifiedName(), + })); + } + + /** + * Throw a validation exception for an abstract class + * @param {string} resourceId - the id of the resouce being validated + * @param {string} propertyName - the name of the property that is not declared + * @param {string} fullyQualifiedTypeName - the fully qualified type being validated + * @throws {ValidationException} the validation exception + * @private + */ + static reportUndeclaredField(resourceId, propertyName, fullyQualifiedTypeName ) { + let formatter = Globalize.messageFormatter('resourcevalidator-undeclaredfield'); + throw new ValidationException(formatter({ + resourceId: resourceId, + propertyName: propertyName, + fullyQualifiedTypeName: fullyQualifiedTypeName + })); + } + + /** + * Throw a validation exception for an invalid field assignment + * @param {string} resourceId - the id of the resouce being validated + * @param {string} propName - the name of the property that is being assigned + * @param {*} obj - the Field + * @param {Field} field - the Field + * @throws {ValidationException} the validation exception + * @private + */ + static reportInvalidFieldAssignment(resourceId, propName, obj, field) { + let formatter = Globalize.messageFormatter('resourcevalidator-invalidfieldassignment'); + let typeName = field.getFullyQualifiedTypeName(); + + if(field.isArray()) { + typeName += '[]'; + } + + throw new ValidationException(formatter({ + resourceId: resourceId, + propertyName: propName, + objectType: obj.$class, + fieldType: typeName + })); + } +} + +module.exports = ObjectValidator; diff --git a/packages/concerto-core/lib/serializer/resourcevalidator.js b/packages/concerto-core/lib/serializer/resourcevalidator.js index 85cff11fe6..e13d92e5ab 100644 --- a/packages/concerto-core/lib/serializer/resourcevalidator.js +++ b/packages/concerto-core/lib/serializer/resourcevalidator.js @@ -20,7 +20,6 @@ const RelationshipDeclaration = require('../introspect/relationshipdeclaration') const EnumDeclaration = require('../introspect/enumdeclaration'); const Relationship = require('../model/relationship'); const Resource = require('../model/resource'); -const Concept = require('../model/concept'); const Identifiable = require('../model/identifiable'); const Util = require('../util'); const ModelUtil = require('../modelutil'); @@ -102,7 +101,7 @@ class ResourceValidator { } if(!found) { - ResourceValidator.reportInvalidEnumValue( parameters.rootResourceIdentifier, enumDeclaration, obj ); + ResourceValidator.reportInvalidEnumValue(parameters.rootResourceIdentifier, enumDeclaration, obj); } return null; @@ -120,7 +119,7 @@ class ResourceValidator { const obj = parameters.stack.pop(); // are we dealing with a Resouce? - if(!((obj instanceof Resource) || (obj instanceof Concept))) { + if(!((obj instanceof Resource))) { ResourceValidator.reportNotResouceViolation(parameters.rootResourceIdentifier, classDeclaration, obj ); } @@ -145,7 +144,7 @@ class ResourceValidator { if(!this.isSystemProperty(propName)) { const field = toBeAssignedClassDeclaration.getProperty(propName); if (!field) { - if(obj instanceof Identifiable) { + if(classDeclaration.getIdentifierFieldName()) { ResourceValidator.reportUndeclaredField(obj.getIdentifier(), propName, toBeAssignedClassDecName); } else { @@ -155,7 +154,7 @@ class ResourceValidator { } } - if(obj instanceof Identifiable) { + if(classDeclaration.getIdentifierFieldName()) { const id = obj.getIdentifier(); // prevent empty identifiers @@ -299,12 +298,16 @@ class ResourceValidator { invalid = true; } break; - case 'Double': case 'Long': case 'Integer': + case 'Double': { if(dataType !== 'number') { invalid = true; } + if (!isFinite(obj)) { + invalid = true; + } + } break; case 'Boolean': if(dataType !== 'boolean') { @@ -392,8 +395,8 @@ class ResourceValidator { const relationshipType = parameters.modelManager.getType(obj.getFullyQualifiedType()); - if(relationshipType.isConcept()) { - throw new Error('Cannot have a relationship to a concept. Relationships must be to resources.'); + if(!relationshipType.getIdentifierFieldName()) { + throw new Error('Cannot have a relationship to a field that is not identifiable.'); } if(!ModelUtil.isAssignableTo(relationshipType.getModelFile(), obj.getFullyQualifiedType(), relationshipDeclaration)) { @@ -421,7 +424,11 @@ class ResourceValidator { else { if(value) { try { - value = JSON.stringify(value); + if (typeof value === 'number' && !isFinite(value)) { + value = value.toString(); + } else { + value = JSON.stringify(value); + } } catch(err) { value = value.toString(); diff --git a/packages/concerto-core/lib/serializer/typedstack.js b/packages/concerto-core/lib/serializer/typedstack.js index 900da42b7a..e6c176c029 100644 --- a/packages/concerto-core/lib/serializer/typedstack.js +++ b/packages/concerto-core/lib/serializer/typedstack.js @@ -14,8 +14,6 @@ 'use strict'; -const Util = require('../util'); - /** * Tracks a stack of typed instances. The type information is used to detect * overflow / underflow bugs by the caller. It also performs basic sanity @@ -45,10 +43,6 @@ class TypedStack { throw new Error('Did not find expected type ' + expectedType.constructor.name + ' as argument to push. Found: ' + obj.toString()); } - if(Util.isNull(obj)) { - throw new Error('Pushing null data!'); - } - this.stack.push(obj); //console.log('Push depth is: ' + this.stack.length + ', contents: ' + this.stack.toString() ); } @@ -81,10 +75,6 @@ class TypedStack { throw new Error('Did not find expected type ' + expectedType + ' on head of stack. Found: ' + result); } - if(Util.isNull(result)) { - throw new Error('Pop returned invalid data'); - } - return result; } diff --git a/packages/concerto-core/lib/serializer/valuegenerator.js b/packages/concerto-core/lib/serializer/valuegenerator.js index 02a7f89f62..e4b48a3133 100644 --- a/packages/concerto-core/lib/serializer/valuegenerator.js +++ b/packages/concerto-core/lib/serializer/valuegenerator.js @@ -16,6 +16,72 @@ const loremIpsum = require('lorem-ipsum'); const Moment = require('moment-mini'); +const RandExp = require('randexp'); + +/** + * Generate a random number within a given range with + * a prescribed precision and inside a global range + * @param {*} userMin - Lower bound on the range, inclusive. Defaults to systemMin + * @param {*} userMax - Upper bound on the range, inclusive. Defaults to systemMax + * @param {*} precision - The precision of values returned, e.g. a value of `1` returns only whole numbers + * @param {*} systemMin - Global minimum on the range, takes precidence over the userMin + * @param {*} systemMax - Global maximum on the range, takes precidence over the userMax + * @return {number} a number + */ +const randomNumberInRangeWithPrecision = function (userMin, userMax, precision, systemMin, systemMax) { + if (userMin === null) { + userMin = systemMin; + } + userMin = Math.min(Math.max(userMin, systemMin), systemMax); + if (userMax === null || userMax > systemMax) { + userMax = systemMax; + } + userMax = Math.max(Math.min(userMax, systemMax), systemMin); + userMax += precision; + userMax = userMax / precision; + userMin = userMin / precision; + let randomNumber = (Math.random() * (userMax - userMin) + userMin); + return randomNumber / (1 / precision); +}; + +/** + * Get a random value from the range. + * @param {number} lowerBound the lower bound on the range, inclusive. + * @param {number} upperBound the upper bound on the range, inclusive. + * @param {string} type the number type for the range, + * `'Long'`, `'Double'`, or `'Integer'` + * @return {number} a number. + * @private + */ +const getRange = (lowerBound, upperBound, type) => { + let min = lowerBound; + let max = upperBound; + if (max !== null && min !== null && max < min) { + min = upperBound; + max = lowerBound; + } + switch(type){ + case 'Long': + return Math.floor( + randomNumberInRangeWithPrecision(min, max, 1, -Math.pow(2, 32), Math.pow(2, 32)) + ); + case 'Integer': { + return Math.floor( + randomNumberInRangeWithPrecision(min, max, 1, -Math.pow(2, 16), Math.pow(2, 16)) + ); + } + case 'Double': { + // IEEE 754 numbers can be larger, + // but we don't need the whole range when generating a sample random number + return Number( + randomNumberInRangeWithPrecision(min, max, 0.0001, -Math.pow(2, 8), Math.pow(2, 8)) + .toFixed(3) + ); + } + default: + return 0; + } +}; /** * Empty value generator. @@ -95,6 +161,27 @@ class EmptyValueGenerator { getArray(valueSupplier) { return []; } + + /** + * Get a default Regex value. + * @param {RegExp} regex A regular expression. + * @return {string} a String value. + */ + getRegex(regex) { + return regex ? new RandExp(regex).gen() : ''; + } + + /** + * Get a random value from the range. + * @param {number} lowerBound the lower bound on the range, inclusive. + * @param {number} upperBound the upper bound on the range, inclusive. + * @param {string} type the number type for the range, + * `'Long'`, `'Double'`, or `'Integer'` + * @return {number} a number. + */ + getRange(lowerBound, upperBound, type) { + return getRange(lowerBound, upperBound, type); + } } /** @@ -175,6 +262,27 @@ class SampleValueGenerator extends EmptyValueGenerator { getArray(valueSupplier) { return [valueSupplier()]; } + + /** + * Get a default Regex value. + * @param {RegExp} regex A regular expression. + * @return {string} a String value. + */ + getRegex(regex) { + return regex ? new RandExp(regex).gen() : ''; + } + + /** + * Get a random value from the range. + * @param {number} lowerBound the lower bound on the range, inclusive. + * @param {number} upperBound the upper bound on the range, inclusive. + * @param {string} type the number type for the range, + * `'Long'`, `'Double'`, or `'Integer'` + * @return {number} a number. + */ + getRange(lowerBound, upperBound, type) { + return getRange(lowerBound, upperBound, type); + } } /** diff --git a/packages/concerto-core/lib/systemmodel.js b/packages/concerto-core/lib/systemmodel.js new file mode 100644 index 0000000000..fde72ac0c7 --- /dev/null +++ b/packages/concerto-core/lib/systemmodel.js @@ -0,0 +1,25 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const systemNamespace = 'system'; +const systemFileName = '@' + systemNamespace + '.cto'; +const systemModel = `namespace system +abstract asset Asset { } +abstract transaction Transaction { } +abstract event Event { } +abstract participant Participant { }`; + +module.exports = { systemNamespace, systemFileName, systemModel }; diff --git a/packages/concerto-core/package-lock.json b/packages/concerto-core/package-lock.json new file mode 100644 index 0000000000..5c6e2c4ff0 --- /dev/null +++ b/packages/concerto-core/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "@accordproject/concerto-core", + "version": "0.82.11", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + } + } +} diff --git a/packages/concerto-core/package.json b/packages/concerto-core/package.json index 6f4900bef2..d18b0cd256 100644 --- a/packages/concerto-core/package.json +++ b/packages/concerto-core/package.json @@ -63,16 +63,15 @@ }, "dependencies": { "axios": "0.19.0", + "colors": "1.4.0", "debug": "4.1.1", - "fast-safe-stringify": "2.0.7", "jsome": "2.5.0", "lorem-ipsum": "1.0.6", "moment-mini": "2.22.1", + "randexp": "0.5.3", "slash": "3.0.0", - "triple-beam": "1.3.0", "urijs": "1.19.1", - "uuid": "3.3.2", - "winston": "3.2.1" + "uuid": "3.3.2" }, "license-check-and-add-config": { "folder": "./lib", @@ -137,8 +136,8 @@ "all": true, "check-coverage": true, "statements": 99, - "branches": 99, - "functions": 100, - "lines": 99 + "branches": 98, + "functions": 99, + "lines": 98 } -} \ No newline at end of file +} diff --git a/packages/concerto-core/test/composer/systemmodel.js b/packages/concerto-core/test/composer/composermodel.js similarity index 83% rename from packages/concerto-core/test/composer/systemmodel.js rename to packages/concerto-core/test/composer/composermodel.js index 0f386edb82..6bd0365e82 100644 --- a/packages/concerto-core/test/composer/systemmodel.js +++ b/packages/concerto-core/test/composer/composermodel.js @@ -14,11 +14,10 @@ 'use strict'; -const SYSTEM_MODELS = [ - +const COMPOSER_MODEL = { - namespace: 'org.hyperledger.composer.system', - fileName: 'org.hyperledger.composer.system.cto', + namespace: 'system', + fileName: 'system.cto', contents: `/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,45 +31,30 @@ const SYSTEM_MODELS = [ * See the License for the specific language governing permissions and * limitations under the License. */ -namespace org.hyperledger.composer.system +namespace system -/** - * Abstract system asset that all assets extend. - * Has no properties, and is soley used as a basis to model other assets. - */ -@docs('asset.md') -abstract asset Asset { } +event Event { +} + +participant Participant { +} + +asset Asset { +} + +transaction Transaction { +} /** * Abstract system participant that all participants extend. * Has no properties, and is soley used as a basis to model other assets. */ @docs('participant.md') -abstract participant Participant { } - -/** - * Abstract transaction that all transactions, including system ones, extend. - * - * Has two properties that are used set and are accessible in all transactions. - * - * - * @param {String} transactionId Identifier for this transaction - */ -@docs('transaction.md') -abstract transaction Transaction identified by transactionId { - o String transactionId +abstract participant ComposerParticipant identified by participantId { + o String participantId } - -/** - * Abstract event that all events, including system ones, extend. - * - * Has two properties that are used set and are accessible in all transactions. - * - * @param {String} eventId Identifier for this event - */ -@docs('event.md') -abstract event Event identified by eventId { - o String eventId +abstract transaction ComposerTransaction identified by transactionId { + o String transactionId } /** @@ -144,7 +128,7 @@ participant NetworkAdmin identified by participantId { * Asset to represent each historian registry entry * * @param {String} transactionId Using the transaction id as the uuid - * @param {Transaction} transactionInvoked Relationship to transaction + * @param {ComposerTransaction} transactionInvoked Relationship to transaction * @param {Participant} participantInvoking Participant who invoked this transaction * @param {Identity} identityUsed The identity that was used by the participant * @param {Event[]} eventsEmitted The events that were emitted by this transactionId @@ -153,13 +137,13 @@ participant NetworkAdmin identified by participantId { @docs('historian.md') @docsuri('Composer Documentation','../business-network/historian') asset HistorianRecord identified by transactionId { - o String transactionId - o String transactionType - --> Transaction transactionInvoked - --> Participant participantInvoking optional - --> Identity identityUsed optional - o Event[] eventsEmitted optional - o DateTime transactionTimestamp + o String transactionId + o String transactionType + --> ComposerTransaction transactionInvoked + --> ComposerParticipant participantInvoking optional + --> Identity identityUsed optional + o Event[] eventsEmitted optional + o DateTime transactionTimestamp } // ----------------------------------------------------------------------------- @@ -169,7 +153,8 @@ asset HistorianRecord identified by transactionId { * @param {Registry} targetRegistry Registry that will be manipulated */ @docs('registryTransaction.md') -abstract transaction RegistryTransaction { +abstract transaction RegistryTransaction identified by transactionId { + o String transactionId --> Registry targetRegistry } @@ -262,7 +247,7 @@ asset Identity identified by identityId { o String issuer o String certificate o IdentityState state - --> Participant participant + --> ComposerParticipant participant } /** @@ -271,8 +256,9 @@ asset Identity identified by identityId { * @param {String} identityName name to use for this identity */ @docs('issueIdentity.md') -transaction IssueIdentity { - --> Participant participant +transaction IssueIdentity identified by transactionId { + o String transactionId + --> ComposerParticipant participant o String identityName } @@ -282,8 +268,9 @@ transaction IssueIdentity { * @param {String} certificate to use */ @docs('bindIdentity.md') -transaction BindIdentity { - --> Participant participant +transaction BindIdentity identified by transactionId { + o String transactionId + --> ComposerParticipant participant o String certificate } @@ -291,7 +278,9 @@ transaction BindIdentity { * Transaction that will activate the current the identity */ @docs('activateIdentity.md') -transaction ActivateCurrentIdentity { } +transaction ActivateCurrentIdentity identified by transactionId { + o String transactionId +} /** * Transaction that will revoke the identity @@ -332,7 +321,6 @@ transaction SetLogLevel { } ` } +; -]; - -module.exports = SYSTEM_MODELS; +module.exports = COMPOSER_MODEL; diff --git a/packages/concerto-core/test/composer/systemmodelutility.js b/packages/concerto-core/test/composer/composermodelutility.js similarity index 54% rename from packages/concerto-core/test/composer/systemmodelutility.js rename to packages/concerto-core/test/composer/composermodelutility.js index 923058291c..23b199c5a7 100644 --- a/packages/concerto-core/test/composer/systemmodelutility.js +++ b/packages/concerto-core/test/composer/composermodelutility.js @@ -14,22 +14,16 @@ 'use strict'; -const debug = require('debug')('concerto-core:systemmodelutility'); - -const SYSTEM_MODELS = require('./systemmodel'); -const ModelUtil = require('../../lib/modelutil'); +const debug = require('debug')('concerto-core:composermodelutility'); +const COMPOSER_MODEL = require('./composermodel'); module.exports = { + addComposerModel: (modelManager) => { + debug('addComposerModel', COMPOSER_MODEL); + modelManager.addModelFile(COMPOSER_MODEL.contents, COMPOSER_MODEL.fileName, true); - addComposerSystemModels: (modelManager) => { - SYSTEM_MODELS.forEach((SYSTEM_MODEL) => { - debug('addComposerSystemModels', SYSTEM_MODEL); - modelManager.addModelFile(SYSTEM_MODEL.contents, SYSTEM_MODEL.fileName, true, true); - }); - - // now validate all the models + // now validate the model modelManager.validateModelFiles(); }, - getSystemModelTable: () => ModelUtil.getIdentitySystemModelTable() }; diff --git a/packages/concerto-core/test/composer/i18n.js b/packages/concerto-core/test/composer/i18n.js index a7d6b5cac2..c7183302f5 100644 --- a/packages/concerto-core/test/composer/i18n.js +++ b/packages/concerto-core/test/composer/i18n.js @@ -23,7 +23,7 @@ const Factory = require('./../../lib/factory'); const Serializer = require('./../../lib/serializer'); const ModelManager = require('./../../lib/modelmanager'); const ModelUtil = require('./../../lib/modelutil'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); describe('Globalization', function() { @@ -113,7 +113,7 @@ describe('Globalization', function() { // create and polulate the modelManager with a model file const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let fileName = './test/composer/models/classdeclaration/validate/foo-identifiernotproperty.cto'; let invalidFile = fs.readFileSync(fileName, 'utf8'); @@ -133,7 +133,7 @@ describe('Globalization', function() { // create and polulate the modelManager with a model file const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let fileName = './test/composer/models/classdeclaration/validate/foo-identifiernotstring.cto'; let invalidFile = fs.readFileSync(fileName, 'utf8'); @@ -164,7 +164,7 @@ describe('Globalization', function() { // create and polulate the modelManager with a model file const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let fileName = './test/composer/models/modelfile/resolvetype/foo-undecltype.cto'; let invalidFile = fs.readFileSync(fileName, 'utf8'); @@ -203,7 +203,7 @@ describe('Globalization', function() { }).should.equal('ModelFile for namespace foo has not been registered with the ModelManager'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); expect(function() { let factory = new Factory(modelManager); @@ -219,7 +219,7 @@ describe('Globalization', function() { }).should.equal('Type bar is not declared in namespace foo'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let fileName = './test/composer/models/factory/newinstance/foo-typenotdeclaredinns.cto'; let file = fs.readFileSync(fileName, 'utf8'); @@ -256,7 +256,7 @@ describe('Globalization', function() { }).should.equal('Type bar is not declared in namespace foo'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let fileName = './test/composer/models/factory/newinstance/foo-typenotdeclaredinns.cto'; let file = fs.readFileSync(fileName, 'utf8'); @@ -278,7 +278,7 @@ describe('Globalization', function() { }).should.equal('ModelFile for namespace foo has not been registered with the ModelManager'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); expect(function() { let factory = new Factory(modelManager); @@ -294,7 +294,7 @@ describe('Globalization', function() { }).should.equal('Type bar is not declared in namespace foo'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let fileName = './test/composer/models/factory/newrelationship/foo-typenotdeclaredinns.cto'; let file = fs.readFileSync(fileName, 'utf8'); @@ -319,7 +319,7 @@ describe('Globalization', function() { }).should.equal('No registered namespace for type bar in foo'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); expect(function() { modelManager.resolveType('foo', 'bar'); @@ -370,7 +370,7 @@ describe('Globalization', function() { formatter().should.equal('Factory cannot be null'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); expect(function() { new Serializer(null, modelManager); }).to.throw(Error, 'Factory cannot be null'); @@ -381,7 +381,7 @@ describe('Globalization', function() { formatter().should.equal('Serializer.toJSON only accepts Concept, Event, Asset, Participant or Transaction.'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); expect(function() { let serializer = new Serializer(true, modelManager); serializer.toJSON({}); diff --git a/packages/concerto-core/test/concerto.js b/packages/concerto-core/test/concerto.js new file mode 100644 index 0000000000..bd6d474b2d --- /dev/null +++ b/packages/concerto-core/test/concerto.js @@ -0,0 +1,422 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const fs = require('fs'); +const chai = require('chai'); + +const expect = chai.expect; +// eslint-disable-next-line no-unused-vars +const should = chai.should(); +chai.use(require('chai-things')); +chai.use(require('chai-as-promised')); + +const ModelManager = require('../lib/modelmanager'); +const Concerto = require('../lib/concerto'); + +describe('concerto', () => { + + let concertoModel = fs.readFileSync('./test/data/model/concerto.cto', 'utf8'); + let concerto; + + beforeEach(() => { + const modelManager = new ModelManager(); + modelManager.addModelFile( concertoModel, 'test.cto'); + concerto = new Concerto(modelManager); + }); + + afterEach(() => { + }); + + describe('#isIdentifiable', () => { + + it('should return the identifier', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + concerto.isIdentifiable(obj).should.be.true; + }); + + it('should not return the identifier', () => { + const obj = { + $class : 'org.accordproject.test.Product', + sku: '001', + description: 'Widgets' + }; + + concerto.isIdentifiable(obj).should.be.false; + }); + + }); + + describe('#getIdentifier', () => { + + it('should return the identifier', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + const ssn = concerto.getIdentifier(obj); + ssn.should.equal('123456789'); + }); + + it('should not return the identifier', () => { + const obj = { + $class : 'org.accordproject.test.Product', + sku: '001', + description: 'Widgets' + }; + + (() => { + concerto.getIdentifier(obj); + }).should.throw(/Object does not have an identifier/); + }); + + }); + + describe('#setIdentifier', () => { + + it('should set the identifier', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + const clone = concerto.setIdentifier(obj, 'abcdefg'); + clone.ssn.should.equal('abcdefg'); + }); + }); + + describe('#getFullyQualifiedIdentifier', () => { + + it('should get the fully qualified identifier', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + const fgid = concerto.getFullyQualifiedIdentifier(obj); + fgid.should.equal('org.accordproject.test.Person#123456789'); + }); + }); + + describe('#toURI', () => { + + it('should get a URI', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + const uri = concerto.toURI(obj); + uri.should.equal('resource:org.accordproject.test.Person#123456789'); + }); + }); + + describe('#fromURI', () => { + + it('should be able to roundtrip toURI and fromURI', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + const uri = concerto.toURI(obj); + const result = concerto.fromURI(uri); + result.typeDeclaration.getName().should.equal('Person'); + result.id.should.equal('123456789'); + }); + }); + + describe('#getTypeDeclaration', () => { + + it('should get type declaration', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + const type = concerto.getTypeDeclaration(obj); + type.getName().should.equal('Person'); + }); + + it('should fail to get type declaration is $class missing', () => { + const obj = { + ssn: '123456789', + name: 'Dan Selman' + }; + + (() => { + concerto.getTypeDeclaration(obj); + }).should.throw(/Input object does not have a \$class attribute./); + }); + + it('should fail to get type declaration is $class in invalid', () => { + const obj = { + $class: 'Foo', + ssn: '123456789', + name: 'Dan Selman' + }; + + (() => { + concerto.getTypeDeclaration(obj); + }).should.throw(/Namespace is not defined for type Foo/); + }); + }); + + describe('#isRelationship', () => { + + it('should identify a relationship', () => { + concerto.isRelationship('resource:org.accordproject.test.Person#001').should.be.true; + }); + + it('should not identify a relationship with wrong scheme', () => { + concerto.isRelationship('foo:org.accordproject.test.Person#001').should.be.false; + }); + + it('should not identify a relationship with wrong type', () => { + concerto.isRelationship(false).should.be.false; + }); + }); + + describe('#getType', () => { + + it('should get type', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + const type = concerto.getType(obj); + type.should.equal('Person'); + }); + }); + + describe('#getNamespace', () => { + + it('should get namespace', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + name: 'Dan Selman' + }; + + const ns = concerto.getNamespace(obj); + ns.should.equal('org.accordproject.test'); + }); + }); + + describe('#instanceOf', () => { + + it('should get instanceOf for sub type', () => { + const obj = { + $class : 'org.accordproject.test.Customer', + ssn: '123456789', + customerId: '001', + name: 'Dan Selman' + }; + + const result = concerto.instanceOf(obj, 'org.accordproject.test.Person'); + result.should.be.true; + }); + + it('should get instanceOf for sub-sub type', () => { + const obj = { + $class : 'org.accordproject.test.Manager', + ssn: '123456789', + customerId: '001', + name: 'Dan Selman' + }; + + const result = concerto.instanceOf(obj, 'org.accordproject.test.Person'); + result.should.be.true; + }); + + it('should get instanceOf for type', () => { + const obj = { + $class : 'org.accordproject.test.Customer', + ssn: '123456789', + customerId: '001', + name: 'Dan Selman' + }; + + const result = concerto.instanceOf(obj, 'org.accordproject.test.Customer'); + result.should.be.true; + }); + + it('should not get instanceOf for derived type', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789' + }; + + const result = concerto.instanceOf(obj, 'org.accordproject.test.Customer'); + expect(result).to.be.false; + }); + + it('all types should be an instance of concerto.Concept', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789' + }; + + const result = concerto.instanceOf(obj, 'concerto.Concept'); + expect(result).to.be.true; + }); + }); + + describe('#validate', () => { + + it('should validate data that conforms to model', () => { + const obj = { + $class : 'org.accordproject.test.Customer', + ssn: '123456789', + customerId: '001', + department: 'ENGINEERING' + }; + + concerto.validate(obj); + }); + + it('should validate data that conforms to model (types)', () => { + const obj = { + $class : 'org.accordproject.test.TestAsset', + id: '001', + types: { + $class : 'org.accordproject.test.Types', + stringValue: 'a', + stringArrayValue : ['a', 'b', 'c'], + longValue: 1, + integerValue: 10, + doubleValue: 5.0, + booleanValue: true, + departmentValue : 'ENGINEERING', + departmentArrayValue : ['ENGINEERING', 'HR'], + relationshipValue: 'resource:org.accordproject.test.Person#ABC', + relationshipArrayValue: ['resource:org.accordproject.test.Person#ABC', 'resource:org.accordproject.test.Person#DEF'], + dateTimeValue: '2020-03-31', + conceptValue : { + $class : 'org.accordproject.test.Product', + sku: 'abc', + description: 'widget' + } + } + }; + + concerto.validate(obj); + }); + + it('should fail with extra property', () => { + const obj = { + $class : 'org.accordproject.test.Customer', + ssn: '123456789', + name: 'Dan', + department: 'ENGINEERING' + }; + + (() => { + concerto.validate(obj); + }).should.throw(/Instance 123456789 has a property named name which is not declared in org.accordproject.test.Customer/); + }); + + it('should fail with extra property (concept)', () => { + const obj = { + $class : 'org.accordproject.test.Product', + sku: '001', + description: 'Widget', + price: 100 + }; + + (() => { + concerto.validate(obj); + }).should.throw(/Instance undefined has a property named price which is not declared in org.accordproject.test.Product/); + }); + + it('should fail with invalid enum', () => { + const obj = { + $class : 'org.accordproject.test.Customer', + ssn: '123456789', + department: 'FOO', + customerId: 'A' + }; + + (() => { + concerto.validate(obj); + }).should.throw(/Instance org.accordproject.test.Customer#123456789 invalid enum value FOO for field Department/); + }); + + it('should fail with empty identifier', () => { + const obj = { + $class : 'org.accordproject.test.Customer', + ssn: '', + department: 'HR', + customerId: 'A' + }; + + (() => { + concerto.validate(obj); + }).should.throw(/Instance org.accordproject.test.Customer# has an empty identifier./); + }); + + it('should fail with missing required property', () => { + const obj = { + $class : 'org.accordproject.test.Customer', + ssn: '001', + customerId: 'A' + }; + + (() => { + concerto.validate(obj); + }).should.throw(/Instance org.accordproject.test.Customer#001 missing required field department/); + }); + + it('should fail with string used for string[]', () => { + const obj = { + $class : 'org.accordproject.test.Employee', + ssn: '001', + department: 'ENGINEERING', + pets: 'cat' + }; + + (() => { + concerto.validate(obj); + }).should.throw(/Model violation in instance org.accordproject.test.Employee#001 field pets has value/); + }); + + it('should fail with abstract type', () => { + const obj = { + $class : 'org.accordproject.test.Person', + ssn: '123456789', + department: 'ENGINEERING', + }; + + (() => { + concerto.validate(obj); + }).should.throw(/The class org.accordproject.test.Person is abstract. Should not have an instance!/); + }); + + }); +}); diff --git a/packages/concerto-core/test/data/model/carlease-nosystem.cto b/packages/concerto-core/test/data/model/carlease-nosystem.cto deleted file mode 100644 index e90824703c..0000000000 --- a/packages/concerto-core/test/data/model/carlease-nosystem.cto +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Car Lease Scenario - * composer Language File - * - * Author: Billy Blockchain - * Version: 1.0 - * Last Updates: 2016-09-22 - */ - -// define the namespace for this model -namespace org.acme - -// define an enumeration -enum State { - o CREATED - o REGISTERED - o SOLD -} - -concept Person { - o String firstName - o String lastName -} - -concept Address { - o String city default="Winchester" - o String country optional - o String state optional - o String street optional - o String zip optional -} - -concept Customer extends Person { - o Address address -} - -/** - * MyParticipant defines an actor in a blockchain based business network - */ -participant MyParticipant identified by id { - o String id -} - -/** - * Define an asset base class. Because this is an abstract asset - * we also declare the name of the field that will identify the instances. - */ -abstract asset Base identified by vin { - // The identifying field must be a String - // Optinally use a regular expression to validate the contents of the field - o String vin regex = /^[A-HJ-NPR-Z]{8}[X][A-HJ-NPR-Z]{2}\d{6}$/ -} - -/** - * Vehicle is the definition of an asset that we will be tracking - * Vehicle extends (augments) the Base asset. The identifying field has already - * been declared, so we do not redeclare it here. - */ -asset Vehicle extends Base { - // An asset contains Fields, each of which can have an optional default value - o String model default="F150" - o String make default="FORD" - o String reg default="ABC123" - // A numeric field can have a range validation expression - o Integer year default=2016 range=[1990,] optional // model year must be 1990 or higher - o Integer[] integerArray - o State state - o Double value - o String colour - o String V5cID regex=/^[A-z][A-z][0-9]{7}/ - o String LeaseContractID - o Boolean scrapped default=false - o DateTime lastUpdate optional - --> MyParticipant owner //relationship to a MyParticipant, with the field named 'owner'. - --> MyParticipant[] previousOwners optional // Nary relationship - o Customer customer -} - -participant Regulator extends MyParticipant { - -} - -// defines a Vehicle transaction type -transaction VehicleTransaction identified by transactionId { - o String transactionId - --> Vehicle vehicle // a VehicleTransaction is related to a Vehicle -} - -transaction VehicleCreated extends VehicleTransaction { -} - -transaction VehicleScrapped extends VehicleTransaction{ -} - -event TestEvent identified by eventId { - o String eventId -} diff --git a/packages/concerto-core/test/data/model/concerto.cto b/packages/concerto-core/test/data/model/concerto.cto new file mode 100644 index 0000000000..384d2897eb --- /dev/null +++ b/packages/concerto-core/test/data/model/concerto.cto @@ -0,0 +1,50 @@ +namespace org.accordproject.test + +enum Department { + o ENGINEERING + o ACCOUNTS + o HR + o SALES +} + +concept Types { + o String stringValue + o String[] stringArrayValue + o Long longValue + o Integer integerValue + o Double doubleValue + o Boolean booleanValue + o DateTime dateTimeValue + o Product conceptValue + o Department departmentValue + o Department[] departmentArrayValue + --> Person relationshipValue + --> Person[] relationshipArrayValue +} + +concept Product { + o String sku + o String description +} + +abstract participant Person identified by ssn { + o String ssn + o Department department + --> Manager manager optional +} + +participant Employee extends Person { + o String[] pets optional +} + +participant Manager extends Person { +} + +participant Customer extends Person { + o String customerId +} + +asset TestAsset identified by id { + o String id + o Types types +} \ No newline at end of file diff --git a/packages/concerto-core/test/data/model/customsystem-base.cto b/packages/concerto-core/test/data/model/customsystem-base.cto deleted file mode 100644 index ab8d9ef140..0000000000 --- a/packages/concerto-core/test/data/model/customsystem-base.cto +++ /dev/null @@ -1,17 +0,0 @@ -namespace org.hyperledger.composer.customsystem - -asset MyAsset identified by myAssetId { - o String myAssetId -} - -participant MyParticipant identified by myParticipantId { - o String myParticipantId -} - -transaction MyTransaction identified by myTransactionId { - o String myTransactionId -} - -event MyEvent identified by myEventId { - o String myEventId -} \ No newline at end of file diff --git a/packages/concerto-core/test/data/model/customsystem-extends.cto b/packages/concerto-core/test/data/model/customsystem-extends.cto deleted file mode 100644 index a264fa4ee4..0000000000 --- a/packages/concerto-core/test/data/model/customsystem-extends.cto +++ /dev/null @@ -1,9 +0,0 @@ -namespace org.acme - -asset YourAsset {} - -participant YourParticipant {} - -transaction YourTransaction {} - -event YourEvent {} diff --git a/packages/concerto-core/test/data/model/dependencies/base/base.cto b/packages/concerto-core/test/data/model/dependencies/base/base.cto index e8e80378d1..eae77c1123 100644 --- a/packages/concerto-core/test/data/model/dependencies/base/base.cto +++ b/packages/concerto-core/test/data/model/dependencies/base/base.cto @@ -24,7 +24,8 @@ enum Gender { o OTHER } -abstract participant Person { +abstract participant Person identified by personId { + o String personId o String firstName optional o String lastName optional o String middleName optional diff --git a/packages/concerto-core/test/data/model/dependencies/business/business.cto b/packages/concerto-core/test/data/model/dependencies/business/business.cto index 7290ed42c9..459e1b745c 100644 --- a/packages/concerto-core/test/data/model/dependencies/business/business.cto +++ b/packages/concerto-core/test/data/model/dependencies/business/business.cto @@ -24,7 +24,8 @@ import stdlib.base.Address /** * An abstract participant type in this business network */ -abstract participant Business { +abstract participant Business identified by businessId { + o String businessId o Address headquarters optional o String name optional --> Manager[] managers optional diff --git a/packages/concerto-core/test/data/model/dependencies2/core.cto b/packages/concerto-core/test/data/model/dependencies2/core.cto index 98b28f6d73..45cf0ade27 100644 --- a/packages/concerto-core/test/data/model/dependencies2/core.cto +++ b/packages/concerto-core/test/data/model/dependencies2/core.cto @@ -18,6 +18,7 @@ participant BaseMember identified by id { o String id } -transaction BaseTransaction { +transaction BaseTransaction identified by transactionId { + o String transactionId --> BaseMember invoker } diff --git a/packages/concerto-core/test/data/model/model-base.cto b/packages/concerto-core/test/data/model/model-base.cto index 60c207e26c..97d1ca050b 100644 --- a/packages/concerto-core/test/data/model/model-base.cto +++ b/packages/concerto-core/test/data/model/model-base.cto @@ -82,17 +82,16 @@ asset DerivedAsset extends BaseAsset { o String anotherStringProperty default="defaultString" } -transaction MyBasicTransaction { - +transaction MyBasicTransaction identified by transactionId { + o String transactionId } asset DerivedDerivedAsset extends DerivedAsset { o MyBasicTransaction includedTransaction } -transaction MyTransaction { +transaction MyTransaction identified { o BaseAsset myAsset - } transaction MyTransactionEx extends MyTransaction { diff --git a/packages/concerto-core/test/data/model/vehicle-lifecycle/composer.base.cto b/packages/concerto-core/test/data/model/vehicle-lifecycle/composer.base.cto index c48050e9e4..6e34886119 100755 --- a/packages/concerto-core/test/data/model/vehicle-lifecycle/composer.base.cto +++ b/packages/concerto-core/test/data/model/vehicle-lifecycle/composer.base.cto @@ -23,7 +23,8 @@ enum Gender { o OTHER } -abstract participant Person { +abstract participant Person identified by personId { + o String personId o String title optional o String firstName optional o String lastName optional diff --git a/packages/concerto-core/test/data/model/vehicle-lifecycle/composer.business.cto b/packages/concerto-core/test/data/model/vehicle-lifecycle/composer.business.cto index d149c78bd4..9123a69439 100755 --- a/packages/concerto-core/test/data/model/vehicle-lifecycle/composer.business.cto +++ b/packages/concerto-core/test/data/model/vehicle-lifecycle/composer.business.cto @@ -19,7 +19,8 @@ import composer.base.Address /** * An abstract participant type in this business network */ -abstract participant Business { +abstract participant Business identified by businessId { + o String businessId o Address headquarters optional o String name optional --> Manager[] managers optional diff --git a/packages/concerto-core/test/data/model/vehicle-lifecycle/org.acme.vehicle.lifecycle.cto b/packages/concerto-core/test/data/model/vehicle-lifecycle/org.acme.vehicle.lifecycle.cto index 14be6d48a0..1fe7f0f690 100755 --- a/packages/concerto-core/test/data/model/vehicle-lifecycle/org.acme.vehicle.lifecycle.cto +++ b/packages/concerto-core/test/data/model/vehicle-lifecycle/org.acme.vehicle.lifecycle.cto @@ -20,11 +20,11 @@ namespace org.acme.vehicle.lifecycle import composer.base.Person import composer.business.Business -participant PrivateOwner identified by email extends Person { +participant PrivateOwner extends Person { o String email } -participant Company identified by companyId extends Business { +participant Company extends Business { o String companyId } diff --git a/packages/concerto-core/test/data/model/vehicle-lifecycle/org.acme.vehicle.lifecycle.manufacturer.cto b/packages/concerto-core/test/data/model/vehicle-lifecycle/org.acme.vehicle.lifecycle.manufacturer.cto index a055d37260..59c60cf85f 100755 --- a/packages/concerto-core/test/data/model/vehicle-lifecycle/org.acme.vehicle.lifecycle.manufacturer.cto +++ b/packages/concerto-core/test/data/model/vehicle-lifecycle/org.acme.vehicle.lifecycle.manufacturer.cto @@ -36,7 +36,7 @@ enum OrderStatus { /** * A manufacturer of vehicles */ -participant Manufacturer identified by companyId extends Business { +participant Manufacturer extends Business { o String companyId } diff --git a/packages/concerto-core/test/data/model/wildcards.cto b/packages/concerto-core/test/data/model/wildcards.cto index 64de753fd7..ea420a154a 100644 --- a/packages/concerto-core/test/data/model/wildcards.cto +++ b/packages/concerto-core/test/data/model/wildcards.cto @@ -20,8 +20,7 @@ concept MyConcept { o Gender gender } -participant MyParticipant identified by participantId extends Person { - o String participantId +participant MyParticipant extends Person { } asset MyAsset identified by assetId { diff --git a/packages/concerto-core/test/demo.js b/packages/concerto-core/test/demo.js new file mode 100644 index 0000000000..56b3b9dc2e --- /dev/null +++ b/packages/concerto-core/test/demo.js @@ -0,0 +1,70 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const ModelManager = require('../lib/modelmanager'); +const Concerto = require('../index').Concerto; + +let concertoModel = ` +namespace org.accordproject.test + +enum Department { + o ENGINEERING + o HR + o SALES + o MARKETING +} + +abstract concept Animal { + o String name +} + +concept Dog extends Animal { +} + +concept Cat extends Animal { +} + + +participant Employee identified by ssn { + o String ssn + o String name optional + o Department department optional + o Animal[] pets optional +} +`; + +const modelManager = new ModelManager(); +modelManager.addModelFile( concertoModel, 'test.cto'); +const obj = { + $class : 'org.accordproject.test.Employee', + ssn: '123456789', + name: 'Dan', + pets : [ + { + $class : 'org.accordproject.test.Cat', + name : 'Bella' + } + ] +}; + +try { + const concerto = new Concerto(modelManager); + concerto.validate(obj); + console.log(`Valid instance: ${concerto.getIdentifier(obj)}`); +} +catch(err) { + console.log(err.message); +} diff --git a/packages/concerto-core/test/factory.js b/packages/concerto-core/test/factory.js index 7452db236a..60ceeb8240 100644 --- a/packages/concerto-core/test/factory.js +++ b/packages/concerto-core/test/factory.js @@ -18,7 +18,7 @@ const Factory = require('../lib/factory'); const ModelManager = require('../lib/modelmanager'); const TypeNotFoundException = require('../lib/typenotfoundexception'); const uuid = require('uuid'); -const Util = require('./composer/systemmodelutility'); +const Util = require('./composer/composermodelutility'); const Moment = require('moment-mini'); const should = require('chai').should(); @@ -34,7 +34,7 @@ describe('Factory', function() { before(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addModelFile(` namespace org.acme.test abstract concept AbstractConcept { @@ -51,10 +51,12 @@ describe('Factory', function() { o String newValue o String optionalValue optional } - transaction MyTransaction { + transaction MyTransaction identified by transactionId { + o String transactionId o String newValue } - event MyEvent { + event MyEvent identified by eventId { + o String eventId o String value }`); factory = new Factory(modelManager); @@ -82,12 +84,6 @@ describe('Factory', function() { }).should.throw(/Missing identifier/); }); - it('should throw creating a new instance with a null ID', function() { - (() => { - factory.newResource(namespace, assetName, null); - }).should.throw(/Invalid or missing identifier/); - }); - it('should throw creating a new instance with an ID of an invalid type', function() { (() => { factory.newResource(namespace, assetName, 1); @@ -119,12 +115,6 @@ describe('Factory', function() { }).should.throw(/AbstractAsset/); }); - it('should throw creating a concept', function() { - (() => { - factory.newResource(namespace, 'MyConcept', 'MY_ID_1'); - }).should.throw(/MyConcept/); - }); - it('should create a new instance with a specified ID', function() { const resource = factory.newResource(namespace, assetName, 'MY_ID_1'); resource.assetId.should.equal('MY_ID_1'); @@ -223,12 +213,6 @@ describe('Factory', function() { }).should.throw(/Cannot instantiate Abstract Type AbstractConcept in namespace org.acme.test/); }); - it('should throw creating a non-concept', function() { - (() => { - factory.newConcept(namespace, assetName); - }).should.throw(new RegExp(assetName)); - }); - it('should create a new concept', () => { let resource = factory.newConcept(namespace, 'MyConcept'); should.equal(resource.newValue, undefined); @@ -302,9 +286,10 @@ describe('Factory', function() { it('should pass options onto newResource', () => { let spy = sandbox.spy(factory, 'newResource'); - factory.newTransaction(namespace, 'MyTransaction', null, { hello: 'world' }); + let resource = factory.newTransaction(namespace, 'MyTransaction', null, { hello: 'world' }); sinon.assert.calledOnce(spy); - sinon.assert.calledWith(spy, namespace, 'MyTransaction', '5604bdfe-7b96-45d0-9883-9c05c18fe638', { hello: 'world' }); + sinon.assert.calledWith(spy, namespace, 'MyTransaction', null, { hello: 'world' }); + resource.transactionId.should.equal('5604bdfe-7b96-45d0-9883-9c05c18fe638'); }); }); @@ -330,7 +315,7 @@ describe('Factory', function() { it('should create a new instance with a generated ID', () => { let resource = factory.newEvent(namespace, 'MyEvent'); - resource.eventId.should.equal('valid'); + resource.eventId.should.equal('5604bdfe-7b96-45d0-9883-9c05c18fe638'); resource.timestamp.should.be.an.instanceOf(Moment); }); @@ -342,9 +327,10 @@ describe('Factory', function() { it('should pass options onto newEvent', () => { let spy = sandbox.spy(factory, 'newResource'); - factory.newEvent(namespace, 'MyEvent', null, { hello: 'world' }); + let resource = factory.newEvent(namespace, 'MyEvent', null, { hello: 'world' }); sinon.assert.calledOnce(spy); - sinon.assert.calledWith(spy, namespace, 'MyEvent', 'valid', { hello: 'world' }); + sinon.assert.calledWith(spy, namespace, 'MyEvent', null, { hello: 'world' }); + resource.eventId.should.equal('5604bdfe-7b96-45d0-9883-9c05c18fe638'); }); }); diff --git a/packages/concerto-core/test/introspect/assetdeclaration.js b/packages/concerto-core/test/introspect/assetdeclaration.js index f158455aa3..a16a074d81 100644 --- a/packages/concerto-core/test/introspect/assetdeclaration.js +++ b/packages/concerto-core/test/introspect/assetdeclaration.js @@ -19,7 +19,6 @@ const AssetDeclaration = require('../../lib/introspect/assetdeclaration'); const ModelFile = require('../../lib/introspect/modelfile'); const ModelManager = require('../../lib/modelmanager'); const fs = require('fs'); -const Util = require('../composer/systemmodelutility'); const should = require('chai').should(); const sinon = require('sinon'); @@ -36,8 +35,6 @@ describe('AssetDeclaration', () => { mockModelManager = sinon.createStubInstance(ModelManager); mockSystemAsset = sinon.createStubInstance(AssetDeclaration); mockSystemAsset.getFullyQualifiedName.returns('org.hyperledger.composer.system.Asset'); - mockModelManager.getSystemTypes.returns([mockSystemAsset]); - mockModelManager.getSystemModelTable.returns(Util.getSystemModelTable()); mockClassDeclaration = sinon.createStubInstance(AssetDeclaration); mockModelManager.getType.returns(mockClassDeclaration); mockClassDeclaration.getProperties.returns([]); diff --git a/packages/concerto-core/test/introspect/classdeclaration.js b/packages/concerto-core/test/introspect/classdeclaration.js index c86c4b3fd1..f8ec5c3310 100644 --- a/packages/concerto-core/test/introspect/classdeclaration.js +++ b/packages/concerto-core/test/introspect/classdeclaration.js @@ -25,7 +25,7 @@ const IntrospectUtils = require('./introspectutils'); const ModelFile = require('../../lib/introspect/modelfile'); const ModelManager = require('../../lib/modelmanager'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const should = require('chai').should(); const sinon = require('sinon'); @@ -38,7 +38,7 @@ describe('ClassDeclaration', () => { beforeEach(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); introspectUtils = new IntrospectUtils(modelManager); modelFile = new ModelFile(modelManager, 'namespace com.hyperledger.testing', 'org.acme.cto'); }); @@ -92,7 +92,7 @@ describe('ClassDeclaration', () => { let asset = introspectUtils.loadLastDeclaration('test/data/parser/classdeclaration.identifierextendsfromsupertype.cto', AssetDeclaration); (() => { asset.validate(); - }).should.throw(/Identifier from super class cannot be redeclared./); + }).should.throw(/Super class com.testing.p1 has an explicit identifier a1 that cannot be redeclared/); }); // TODO: This has been disabled pending major version bump and/or confirmation that this is illegal @@ -165,7 +165,7 @@ describe('ClassDeclaration', () => { } }); clz.getName().should.equal('suchName'); - clz.toString().should.equal('ClassDeclaration {id=com.hyperledger.testing.suchName enum=false abstract=false}'); + clz.toString().should.equal('ClassDeclaration {id=com.hyperledger.testing.suchName super=Concept enum=false abstract=false}'); }); }); @@ -212,16 +212,16 @@ describe('ClassDeclaration', () => { superclassName.should.equal('com.testing.parent.Super'); }); - it('should return system type when none exists', function() { + it('should return concerto.Concept when no super type exists', function() { const baseclass = modelManager.getType('com.testing.parent.Base'); should.exist(baseclass); const superclassName = baseclass.getSuperType(); - should.equal(superclassName,'org.hyperledger.composer.system.Participant'); + should.equal(superclassName,'concerto.Concept'); }); it('toString',()=>{ const baseclass = modelManager.getType('com.testing.parent.Base'); - baseclass.toString().should.equal('ClassDeclaration {id=com.testing.parent.Base super=Participant enum=false abstract=true}'); + baseclass.toString().should.equal('ClassDeclaration {id=com.testing.parent.Base super=Concept enum=false abstract=true}'); }); }); @@ -280,17 +280,17 @@ describe('ClassDeclaration', () => { describe('#_resolveSuperType', () => { - it('should return null if no super type', () => { - let classDecl = modelManager.getType('org.hyperledger.composer.system.Asset'); - should.equal(classDecl._resolveSuperType(), null); + it('should return Concept if no super type', () => { + let classDecl = modelManager.getType('system.Asset'); + classDecl._resolveSuperType().should.not.be.null; }); - it('should return the super class declaration for a system super class', () => { + it('should return Concept for a super class', () => { modelManager.addModelFile(`namespace org.acme asset TestAsset identified by assetId { o String assetId }`); let classDecl = modelManager.getType('org.acme.TestAsset'); let superClassDecl = classDecl._resolveSuperType(); - superClassDecl.getFullyQualifiedName().should.equal('org.hyperledger.composer.system.Asset'); + should.equal(superClassDecl.getName(), 'Concept'); }); it('should return the super class declaration for a super class in the same file', () => { @@ -317,32 +317,10 @@ describe('ClassDeclaration', () => { describe('#getSuperTypeDeclaration', () => { - it('should return null if no super type', () => { - let classDecl = modelManager.getType('org.hyperledger.composer.system.Asset'); - should.equal(classDecl.getSuperTypeDeclaration(), null); + it('should return Concept if no super type', () => { + let classDecl = modelManager.getType('system.Asset'); + classDecl.getSuperTypeDeclaration().should.not.be.null; }); - - it('should resolve the super type if not already resolved', () => { - modelManager.addModelFile(`namespace org.acme - asset TestAsset identified by assetId { o String assetId }`); - let classDecl = modelManager.getType('org.acme.TestAsset'); - classDecl.superTypeDeclaration = null; - let spy = sinon.spy(classDecl, '_resolveSuperType'); - let superClassDecl = classDecl.getSuperTypeDeclaration(); - superClassDecl.getFullyQualifiedName().should.equal('org.hyperledger.composer.system.Asset'); - sinon.assert.calledOnce(spy); - }); - - it('should not resolve the super type if not already resolved', () => { - modelManager.addModelFile(`namespace org.acme - asset TestAsset identified by assetId { o String assetId }`); - let classDecl = modelManager.getType('org.acme.TestAsset'); - let spy = sinon.spy(classDecl, '_resolveSuperType'); - let superClassDecl = classDecl.getSuperTypeDeclaration(); - superClassDecl.getFullyQualifiedName().should.equal('org.hyperledger.composer.system.Asset'); - sinon.assert.notCalled(spy); - }); - }); describe('#validation', function() { @@ -384,12 +362,12 @@ describe('ClassDeclaration', () => { modelManager.addModelFiles(modelFiles); }); - it('should return array with only system types if there are no superclasses', function() { + it('should return an array with Concept if there are no superclasses', function() { const testClass = modelManager.getType('com.testing.parent.Base'); should.exist(testClass); const superclasses = testClass.getAllSuperTypeDeclarations(); const superclassNames = superclasses.map(classDef => classDef.getName()); - superclassNames.should.have.members(['Participant']); + superclassNames.should.have.length(1); }); it('should return all superclass definitions', function() { @@ -397,7 +375,7 @@ describe('ClassDeclaration', () => { should.exist(testClass); const superclasses = testClass.getAllSuperTypeDeclarations(); const superclassNames = superclasses.map(classDef => classDef.getName()); - superclassNames.should.have.same.members(['Base', 'Super','Participant']); + superclassNames.should.have.same.members(['Base', 'Super', 'Concept']); }); }); @@ -417,38 +395,4 @@ describe('ClassDeclaration', () => { }); }); - - describe('#isRelationshipTarget', () => { - const modelFileNames = [ - 'test/data/parser/classdeclaration.isrelationshiptarget.cto', - ]; - - beforeEach(() => { - const modelFiles = introspectUtils.loadModelFiles(modelFileNames, modelManager); - modelManager.addModelFiles(modelFiles); - }); - - it('should return false', () => { - const testClass = modelManager.getType('com.testing.Test'); - testClass.isRelationshipTarget().should.be.false; - - }); - }); - - describe('#isSystemRelationshipTarget', () => { - const modelFileNames = [ - 'test/data/parser/classdeclaration.isrelationshiptarget.cto', - ]; - - beforeEach(() => { - const modelFiles = introspectUtils.loadModelFiles(modelFileNames, modelManager); - modelManager.addModelFiles(modelFiles); - }); - - it('should return false', () => { - const testClass = modelManager.getType('com.testing.Test'); - testClass.isSystemRelationshipTarget().should.be.false; - - }); - }); }); diff --git a/packages/concerto-core/test/introspect/decorators.js b/packages/concerto-core/test/introspect/decorators.js index e8b1015021..1335454c01 100644 --- a/packages/concerto-core/test/introspect/decorators.js +++ b/packages/concerto-core/test/introspect/decorators.js @@ -19,7 +19,7 @@ const DecoratorFactory = require('../../lib/introspect/decoratorfactory'); const ModelManager = require('../../lib/modelmanager'); const Introspector = require('../../lib/introspect/introspector'); const fs = require('fs'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const should = require('chai').should(); const sinon = require('sinon'); @@ -81,7 +81,7 @@ describe('Decorators', () => { it('should allow all valid syntax and attach to model elements', () => { const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let modelDefinitions = fs.readFileSync('test/data/decorators/model.cto', 'utf8'); modelManager.addModelFile(modelDefinitions); const introspector = new Introspector(modelManager); @@ -168,7 +168,7 @@ describe('Decorators', () => { (() => { const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let modelDefinitions = fs.readFileSync('test/data/decorators/invalid.cto', 'utf8'); modelManager.addModelFile(modelDefinitions); }).should.throw(/Duplicate decorator/); @@ -214,7 +214,7 @@ describe('Decorators', () => { }); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addDecoratorFactory(decoratorFactory); let modelDefinitions = fs.readFileSync('test/data/decorators/model.cto', 'utf8'); modelManager.addModelFile(modelDefinitions); diff --git a/packages/concerto-core/test/introspect/enumdeclaration.js b/packages/concerto-core/test/introspect/enumdeclaration.js index 25b657069f..34be6a2845 100644 --- a/packages/concerto-core/test/introspect/enumdeclaration.js +++ b/packages/concerto-core/test/introspect/enumdeclaration.js @@ -15,18 +15,16 @@ 'use strict'; const EnumDeclaration = require('../../lib/introspect/enumdeclaration'); -const EventDeclaration = require('../../lib/introspect/eventdeclaration'); const EnumValueDeclaration = require('../../lib/introspect/enumvaluedeclaration'); const ModelFile = require('../../lib/introspect/modelfile'); const ModelManager = require('../../lib/modelmanager'); const fs = require('fs'); require('chai').should(); -const sinon = require('sinon'); describe('EnumDeclaration', () => { - let mockModelManager; + let modelManager; /** * Load an arbitrary number of model files. @@ -46,7 +44,7 @@ describe('EnumDeclaration', () => { }; const loadModelFile = (modelFileName) => { - return loadModelFiles([modelFileName], mockModelManager)[0]; + return loadModelFiles([modelFileName], modelManager)[0]; }; const loadLastDeclaration = (modelFileName, type) => { @@ -55,19 +53,11 @@ describe('EnumDeclaration', () => { return declarations[declarations.length - 1]; }; - let sandbox; - let mockSystemEvent; - beforeEach(() => { - sandbox = sinon.createSandbox(); - mockModelManager = sinon.createStubInstance(ModelManager); - mockSystemEvent = sinon.createStubInstance(EventDeclaration); - mockSystemEvent.getFullyQualifiedName.returns('org.hyperledger.composer.system.Event'); - mockModelManager.getSystemTypes.returns([mockSystemEvent]); + modelManager = new ModelManager(); }); afterEach(() => { - sandbox.restore(); }); describe('#toString', () => { diff --git a/packages/concerto-core/test/introspect/eventdeclaration.js b/packages/concerto-core/test/introspect/eventdeclaration.js index 72cc64218a..ec11eb16a5 100644 --- a/packages/concerto-core/test/introspect/eventdeclaration.js +++ b/packages/concerto-core/test/introspect/eventdeclaration.js @@ -14,28 +14,19 @@ 'use strict'; -const EventDeclaration = require('../../lib/introspect/eventdeclaration'); const ModelManager = require('../../lib/modelmanager'); const fs = require('fs'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); require('chai').should(); const sinon = require('sinon'); describe('EventDeclaration', () => { - let mockModelManager; - let mockSystemEvent; - let sandbox; beforeEach(() => { sandbox = sinon.createSandbox(); - mockModelManager = sinon.createStubInstance(ModelManager); - mockSystemEvent = sinon.createStubInstance(EventDeclaration); - mockSystemEvent.getFullyQualifiedName.returns('org.hyperledger.composer.system.Event'); - mockModelManager.getSystemTypes.returns([mockSystemEvent]); - mockModelManager.getSystemModelTable.returns(Util.getSystemModelTable()); }); afterEach(() => { @@ -52,12 +43,10 @@ describe('EventDeclaration', () => { o String euid }`; const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); const modelFile = modelManager.addModelFile(model, 'awesome.cto' ); let ed = modelFile.getEventDeclaration('E'); - let stub = sinon.stub(ed,'getSystemType'); - stub.throws(new Error()); ed.validate(); }); @@ -71,7 +60,7 @@ describe('EventDeclaration', () => { const fileName = 'test/data/model/events.cto'; let modelDefinitions = fs.readFileSync(fileName, 'utf8'); const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); const modelFile = modelManager.addModelFile(modelDefinitions, fileName ); const abstractEvent = modelFile.getEventDeclaration('AbstractEvent'); diff --git a/packages/concerto-core/test/introspect/identifieddeclaration.js b/packages/concerto-core/test/introspect/identifieddeclaration.js new file mode 100644 index 0000000000..dbdf390a76 --- /dev/null +++ b/packages/concerto-core/test/introspect/identifieddeclaration.js @@ -0,0 +1,215 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const ModelManager = require('../../lib/modelmanager'); +const IdentifiedDeclaration = require('../../lib/introspect/identifieddeclaration'); + +require('chai').should(); + +describe('IdentifiedDeclaration', () => { + + beforeEach(() => { + }); + + afterEach(() => { + }); + + describe('#hasInstance', () => { + + it('should identify instance', () => { + const mm = new ModelManager(); + mm.addModelFile( ` +namespace test + +asset Order { + o Double price +} + `, 'test.cto'); + + const order = mm.getType('test.Order'); + order.should.not.be.null; + (order instanceof IdentifiedDeclaration).should.be.true; + }); + }); + + describe('#identified', () => { + + it('should create a system identifier', () => { + const mm = new ModelManager(); + mm.addModelFile( ` +namespace test + +asset Order { + o Double price +} + `, 'test.cto'); + + const order = mm.getType('test.Order'); + order.should.not.be.null; + order.getProperties().length.should.equal(2); + order.getIdentifierFieldName().should.equal('$identifier'); + }); + + it('should allow declaring system identifier', () => { + const mm = new ModelManager(); + mm.addModelFile( ` +namespace test + +asset Order identified { + o Double price +} + `, 'test.cto'); + + const order = mm.getType('test.Order'); + order.should.not.be.null; + order.getProperties().length.should.equal(2); + order.getIdentifierFieldName().should.equal('$identifier'); + }); + + it('should allow declaring explicit identifier', () => { + const mm = new ModelManager(); + mm.addModelFile( ` +namespace test + +asset Order identified by sku { + o String sku + o Double price +} + `, 'test.cto'); + + const order = mm.getType('test.Order'); + order.should.not.be.null; + order.getProperties().length.should.equal(2); + order.getIdentifierFieldName().should.equal('sku'); + order.isSystemIdentified().should.be.false; + order.isExplicitlyIdentified().should.be.true; + }); + + it('should not allow overriding explicit identifier', () => { + const mm = new ModelManager(); + + (() => { + mm.addModelFile( ` + namespace test + + asset Order identified by sku { + o String sku + o Double price + } + + asset FancyOrder identified extends Order { + } + + `, 'test.cto'); + }).should.throw(/Super class test.Order has an explicit identifier sku that cannot be redeclared./); + }); + + it('should not allow overriding system identifier', () => { + const mm = new ModelManager(); + + (() => { + mm.addModelFile( ` + namespace test + + asset Order identified { + o Double price + } + + asset FancyOrder identified extends Order { + o String sku + } + + `, 'test.cto'); + }).should.throw(/Class FancyOrder has more than one field named \(\$identifier\)/); + }); + + it('should not allow overriding explicit identifier with a system identifier', () => { + const mm = new ModelManager(); + + (() => { + mm.addModelFile( ` + namespace test + + asset Order identified by sku { + o Double price + o String sku + } + + asset FancyOrder identified extends Order { + o String model + } + + `, 'test.cto'); + }).should.throw(/Super class test.Order has an explicit identifier sku that cannot be redeclared./); + }); + + it('should not allow overriding explicit identifier with an explicit identifier', () => { + const mm = new ModelManager(); + + (() => { + mm.addModelFile( ` + namespace test + + asset Order identified by sku { + o Double price + o String sku + } + + asset FancyOrder identified by model extends Order { + o String model + } + + `, 'test.cto'); + }).should.throw(/Super class test.Order has an explicit identifier sku that cannot be redeclared./); + }); + + it('should not allow field called $identifier', () => { + const mm = new ModelManager(); + + (() => { + mm.addModelFile( ` + namespace test + + asset Order { + o String $identifier + }`, 'test.cto'); + }).should.throw(/Invalid field name \$identifier/); + }); + + it('should allow abstract assets without an identifier', () => { + const mm = new ModelManager(); + mm.addModelFile( ` + namespace test + + abstract asset Order { + o Double price + } + + asset FancyOrder identified by sku extends Order { + o String sku + } + `, 'test.cto'); + + const order = mm.getType('test.Order'); + order.should.not.be.null; + order.getProperties().length.should.equal(2); + order.isSystemIdentified().should.be.true; + order.isExplicitlyIdentified().should.be.false; + order.getIdentifierFieldName().should.equal('$identifier'); + }); + + }); +}); diff --git a/packages/concerto-core/test/introspect/introspector.js b/packages/concerto-core/test/introspect/introspector.js index 247bfb4bf7..c402d6e836 100644 --- a/packages/concerto-core/test/introspect/introspector.js +++ b/packages/concerto-core/test/introspect/introspector.js @@ -16,7 +16,7 @@ const ModelManager = require('../../lib/modelmanager'); const Introspector = require('../../lib/introspect/introspector'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const fs = require('fs'); @@ -46,7 +46,7 @@ describe('Introspector', () => { it('should return all class declarations', () => { // create and populate the ModelManager with a model file const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; let modelBase = fs.readFileSync('./test/data/model/model-base.cto', 'utf8'); @@ -54,10 +54,8 @@ describe('Introspector', () => { modelManager.addModelFile(modelBase, 'model-base.cto'); const introspector = new Introspector(modelManager); - let classDecl = introspector.getClassDeclarations().filter( (element) => { - return !element.isSystemType(); - }); - classDecl.length.should.equal(13); + let classDecl = introspector.getClassDeclarations(); + classDecl.length.should.equal(44); }); }); @@ -66,7 +64,7 @@ describe('Introspector', () => { it('should be able to get a single class declaration', () => { // create and populate the ModelManager with a model file const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; let modelBase = fs.readFileSync('./test/data/model/model-base.cto', 'utf8'); @@ -82,7 +80,7 @@ describe('Introspector', () => { it('should return the model manager', () => { const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); const introspector = new Introspector(modelManager); introspector.getModelManager().should.equal(modelManager); }); diff --git a/packages/concerto-core/test/introspect/modelfile.js b/packages/concerto-core/test/introspect/modelfile.js index daf5bfd6d0..49f88c3270 100644 --- a/packages/concerto-core/test/introspect/modelfile.js +++ b/packages/concerto-core/test/introspect/modelfile.js @@ -26,7 +26,7 @@ const ParseException = require('../../lib/introspect/parseexception'); const parser = require('../../lib/introspect/parser'); const fs = require('fs'); const path = require('path'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const chai = require('chai'); const should = chai.should(); @@ -41,7 +41,7 @@ describe('ModelFile', () => { beforeEach(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); sandbox = sinon.createSandbox(); }); @@ -89,7 +89,7 @@ describe('ModelFile', () => { }; sandbox.stub(parser, 'parse').returns(ast); let mf = new ModelFile(modelManager, 'fake definitions'); - mf.imports.should.deep.equal(['org.hyperledger.composer.system.Event', 'org.hyperledger.composer.system.Transaction', 'org.hyperledger.composer.system.Participant', 'org.hyperledger.composer.system.Asset', 'org.freddos', 'org.doge']); + mf.imports.should.deep.equal(['org.freddos', 'org.doge', 'concerto.Concept']); }); it('should call the parser with the definitions and save imports with uris', () => { @@ -101,7 +101,7 @@ describe('ModelFile', () => { }; sandbox.stub(parser, 'parse').returns(ast); let mf = new ModelFile(modelManager, 'fake definitions'); - mf.imports.should.deep.equal(['org.hyperledger.composer.system.Event', 'org.hyperledger.composer.system.Transaction', 'org.hyperledger.composer.system.Participant', 'org.hyperledger.composer.system.Asset', 'org.doge', 'org.freddos.*']); + mf.imports.should.deep.equal(['org.doge', 'org.freddos.*', 'concerto.Concept']); mf.getImportURI('org.freddos.*').should.equal('https://freddos.org/model.cto'); (mf.getImportURI('org.doge') === null).should.be.true; }); @@ -371,13 +371,6 @@ describe('ModelFile', () => { describe('#resolveImport', () => { - it('should find the fully qualified name of a type in the system namespace', () => { - const model = ` - namespace org.acme`; - let modelFile = new ModelFile(modelManager, model); - modelFile.resolveImport('Asset').should.equal('org.hyperledger.composer.system.Asset'); - }); - it('should find the fully qualified name of the import', () => { const model = ` namespace org.acme @@ -479,7 +472,7 @@ describe('ModelFile', () => { before(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelFile = modelManager.addModelFile(`namespace org.acme asset MyAsset identified by assetId { o String assetId @@ -605,41 +598,18 @@ describe('ModelFile', () => { it('should return the expected number of Event declarations without system types', () => { let modelFile = new ModelFile(modelManager, carLeaseModel); - let events = modelFile.getEventDeclarations(false); + let events = modelFile.getEventDeclarations(); events.length.should.equal(1); - let i; - for(i = 0; i < events.length; i++) { - events[i].modelFile.should.have.property('systemModelFile', false); - } }); }); describe('#getEnumDeclarations', () => { - it('should return the expected number of Enum declarations with system types', () => { + it('should return the expected number of Enum declarations', () => { let modelFile = new ModelFile(modelManager, carLeaseModel); let decls = modelFile.getEnumDeclarations(); decls.should.all.be.an.instanceOf(EnumDeclaration); decls.length.should.equal(1); - // TO DO ADD IN CHECK FOR TRUE AND FALSE, CHECK THAT SYSTEM TYPE IS CORRECT USING FOR LOOP LIKE EARLIER - }); - - it('should return the expected number of Enum declarations with system types', () => { - let modelFile = new ModelFile(modelManager, carLeaseModel); - let decls = modelFile.getEnumDeclarations(true); - decls.should.all.be.an.instanceOf(EnumDeclaration); - decls.length.should.equal(1); - }); - - it('should return the expected number of Enum declarations without system types', () => { - let modelFile = new ModelFile(modelManager, carLeaseModel); - let decls = modelFile.getEnumDeclarations(false); - decls.should.all.be.an.instanceOf(EnumDeclaration); - decls.length.should.equal(1); - let i; - for(i = 0; i < decls.length; i++) { - decls[i].modelFile.should.have.property('systemModelFile', false); - } }); }); diff --git a/packages/concerto-core/test/introspect/participantdeclaration.js b/packages/concerto-core/test/introspect/participantdeclaration.js index 637f4423c5..58aee1af28 100644 --- a/packages/concerto-core/test/introspect/participantdeclaration.js +++ b/packages/concerto-core/test/introspect/participantdeclaration.js @@ -14,10 +14,8 @@ 'use strict'; -const ModelFile = require('../../lib/introspect/modelfile'); const ModelManager = require('../../lib/modelmanager'); -const fs = require('fs'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); require('chai').should(); @@ -27,30 +25,13 @@ describe('ParticipantDeclaration', () => { beforeEach(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); }); - let loadParticipantDeclaration = (modelFileName) => { - let modelDefinitions = fs.readFileSync(modelFileName, 'utf8'); - let modelFile = new ModelFile(modelManager, modelDefinitions); - let assets = modelFile.getParticipantDeclarations(); - assets.should.have.lengthOf(1); - - return assets[0]; - }; - - describe('#isRelationshipTarget', () => { - it('should return true', () => { - let p = loadParticipantDeclaration('test/data/parser/participantdeclaration.valid.cto'); - p.isRelationshipTarget().should.be.true; - }); - }); - - describe('#getSystemType', () => { - it('should return Participant', () => { - let p = loadParticipantDeclaration('test/data/parser/participantdeclaration.valid.cto'); - p.getSystemType().should.equal('Participant'); + describe('#getParticipantDeclarations', () => { + it('should get participants', () => { + let assets = modelManager.getParticipantDeclarations(); + assets.should.have.lengthOf(3); }); }); - }); diff --git a/packages/concerto-core/test/introspect/property_ex.js b/packages/concerto-core/test/introspect/property_ex.js index 58e6b3add6..4874931f8e 100644 --- a/packages/concerto-core/test/introspect/property_ex.js +++ b/packages/concerto-core/test/introspect/property_ex.js @@ -16,7 +16,7 @@ const ModelManager = require('../../lib/modelmanager'); const sinon = require('sinon'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const chai = require('chai'); chai.should(); @@ -38,7 +38,7 @@ describe('Property', function () { before(function () { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); }); beforeEach(function () { diff --git a/packages/concerto-core/test/introspect/relationshipdeclaration.js b/packages/concerto-core/test/introspect/relationshipdeclaration.js index de38ce01c6..a45e1d2d40 100644 --- a/packages/concerto-core/test/introspect/relationshipdeclaration.js +++ b/packages/concerto-core/test/introspect/relationshipdeclaration.js @@ -18,7 +18,7 @@ const ModelManager = require('../../lib/modelmanager'); const sinon = require('sinon'); const ClassDeclaration = require('../../lib/introspect/classdeclaration'); const RelationshipDeclaration = require('../../lib/introspect/relationshipdeclaration'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const chai = require('chai'); chai.should(); @@ -42,7 +42,7 @@ describe('RelationshipDeclaration', function () { beforeEach(function () { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); mockClassDeclaration = sinon.createStubInstance(ClassDeclaration); mockClassDeclaration.getModelFile.returns(mockClassDeclaration); }); @@ -105,12 +105,11 @@ describe('RelationshipDeclaration', function () { const vehicleDeclaration = modelManager.getType('org.acme.l1.Car'); const field = vehicleDeclaration.getProperty('owner'); (field instanceof RelationshipDeclaration).should.be.true; - mockClassDeclaration.isRelationshipTarget.returns(false); field.getParent().getModelFile().getType = () => {return mockClassDeclaration;}; (function () { field.validate(vehicleDeclaration); - }).should.throw(/Relationship owner must be to an asset or participant/); + }).should.throw(/Relationship owner must be to a class that has an identifier/); }); }); }); diff --git a/packages/concerto-core/test/introspect/semantic_validation.js b/packages/concerto-core/test/introspect/semantic_validation.js index 9d67a3bc3d..2b33d90d2c 100644 --- a/packages/concerto-core/test/introspect/semantic_validation.js +++ b/packages/concerto-core/test/introspect/semantic_validation.js @@ -14,52 +14,31 @@ 'use strict'; -const AssetDeclaration = require('../../lib/introspect/assetdeclaration'); const ModelFile = require('../../lib/introspect/modelfile'); const ModelManager = require('../../lib/modelmanager'); -const ClassDeclaration = require('../../lib/introspect/classdeclaration'); const fs = require('fs'); const path = require('path'); -const Util = require('../composer/systemmodelutility'); require('chai').should(); -const sinon = require('sinon'); describe('ModelFile semantic validation', () => { const invalidModel = fs.readFileSync(path.resolve(__dirname, '../data/model/invalid.cto'), 'utf8'); - let mockModelManager; - let mockClassDeclaration; - let mockSystemModelFile; - let mockSystemAsset; - let sandbox; + let modelManager = null; beforeEach(() => { - mockSystemModelFile = sinon.createStubInstance(ModelFile); - mockSystemModelFile.isLocalType.withArgs('Asset').returns(true); - mockSystemModelFile.getNamespace.returns('org.hyperledger.composer.system'); - mockModelManager = sinon.createStubInstance(ModelManager); - mockModelManager.getModelFile.withArgs('org.hyperledger.composer.system').returns(mockSystemModelFile); - mockSystemAsset = sinon.createStubInstance(AssetDeclaration); - mockSystemAsset.getFullyQualifiedName.returns('org.hyperledger.composer.system.Asset'); - mockModelManager.getSystemTypes.returns([mockSystemAsset]); - mockModelManager.getSystemModelTable.returns(Util.getSystemModelTable()); - mockClassDeclaration = sinon.createStubInstance(ClassDeclaration); - mockModelManager.getType.returns(mockClassDeclaration); - mockClassDeclaration.getProperties.returns([]); - sandbox = sinon.createSandbox(); + modelManager = new ModelManager(); }); afterEach(() => { - sandbox.restore(); }); describe('#constructor', () => { it('should throw and include file location', () => { try { - const mf = new ModelFile(mockModelManager,invalidModel, 'invalid.cto'); + const mf = new ModelFile(modelManager,invalidModel, 'invalid.cto'); mf.validate(); } catch(error) { diff --git a/packages/concerto-core/test/introspect/transactiondeclaration.js b/packages/concerto-core/test/introspect/transactiondeclaration.js index db0cbc1411..98425367a3 100644 --- a/packages/concerto-core/test/introspect/transactiondeclaration.js +++ b/packages/concerto-core/test/introspect/transactiondeclaration.js @@ -14,17 +14,15 @@ 'use strict'; -const TransactionDeclaration = require('../../lib/introspect/transactiondeclaration'); const ClassDeclaration = require('../../lib/introspect/classdeclaration'); const ModelFile = require('../../lib/introspect/modelfile'); const ModelManager = require('../../lib/modelmanager'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); require('chai').should(); const sinon = require('sinon'); describe('TransactionDeclaration', () => { - let mockSystemTransaction; let mockClassDeclaration; let sandbox; let modelManager; @@ -32,9 +30,7 @@ describe('TransactionDeclaration', () => { beforeEach(() => { sandbox = sinon.createSandbox(); modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); - mockSystemTransaction = sinon.createStubInstance(TransactionDeclaration); - mockSystemTransaction.getFullyQualifiedName.returns('org.hyperledger.composer.system.Transaction'); + Util.addComposerModel(modelManager); mockClassDeclaration = sinon.createStubInstance(ClassDeclaration); mockClassDeclaration.getProperties.returns([]); }); @@ -53,8 +49,6 @@ describe('TransactionDeclaration', () => { const modelFile = new ModelFile(modelManager, model); let td = modelFile.getTransactionDeclaration('T'); - - sinon.stub(td,'getSystemType').throws(new Error('fred')); td.validate(); }); diff --git a/packages/concerto-core/test/introspect/types.js b/packages/concerto-core/test/introspect/types.js index f63f385d5c..3cf518504b 100644 --- a/packages/concerto-core/test/introspect/types.js +++ b/packages/concerto-core/test/introspect/types.js @@ -14,49 +14,30 @@ 'use strict'; -const AssetDeclaration = require('../../lib/introspect/assetdeclaration'); -const ClassDeclaration = require('../../lib/introspect/classdeclaration'); const ModelFile = require('../../lib/introspect/modelfile'); const ModelManager = require('../../lib/modelmanager'); const fs = require('fs'); const path = require('path'); require('chai').should(); -const sinon = require('sinon'); describe('ModelFile type parsing', () => { const invalidModel = fs.readFileSync(path.resolve(__dirname, '../data/parser/types.cto'), 'utf8'); - let mockModelManager; - let mockClassDeclaration; - let mockSystemModelFile; - let mockSystemAsset; - let sandbox; + let modelManager; beforeEach(() => { - mockSystemModelFile = sinon.createStubInstance(ModelFile); - mockSystemModelFile.isLocalType.withArgs('Asset').returns(true); - mockSystemModelFile.getNamespace.returns('org.hyperledger.composer.system'); - mockModelManager = sinon.createStubInstance(ModelManager); - mockModelManager.getModelFile.withArgs('org.hyperledger.composer.system').returns(mockSystemModelFile); - mockSystemAsset = sinon.createStubInstance(AssetDeclaration); - mockSystemAsset.getFullyQualifiedName.returns('org.hyperledger.composer.system.Asset'); - mockModelManager.getSystemTypes.returns([mockSystemAsset]); - mockClassDeclaration = sinon.createStubInstance(ClassDeclaration); - mockModelManager.getType.returns(mockClassDeclaration); - mockClassDeclaration.getProperties.returns([]); - sandbox = sinon.createSandbox(); + modelManager = new ModelManager(); }); afterEach(() => { - sandbox.restore(); }); describe('#constructor', () => { it('should be valid', () => { - const mf = new ModelFile(mockModelManager,invalidModel, 'types.cto'); + const mf = new ModelFile(modelManager,invalidModel, 'types.cto'); mf.validate(); }); @@ -69,7 +50,7 @@ describe('ModelFile type parsing', () => { } `; (() => { - const mf = new ModelFile(mockModelManager, model, 'test.cto'); + const mf = new ModelFile(modelManager, model, 'test.cto'); mf.validate(); }).should.throw(); }); @@ -83,7 +64,7 @@ describe('ModelFile type parsing', () => { } `; (() => { - const mf = new ModelFile(mockModelManager, model, 'test.cto'); + const mf = new ModelFile(modelManager, model, 'test.cto'); mf.validate(); }).should.throw(); }); @@ -97,7 +78,7 @@ describe('ModelFile type parsing', () => { } `; (() => { - const mf = new ModelFile(mockModelManager, model, 'test.cto'); + const mf = new ModelFile(modelManager, model, 'test.cto'); mf.validate(); }).should.throw(); }); @@ -111,7 +92,7 @@ describe('ModelFile type parsing', () => { } `; (() => { - const mf = new ModelFile(mockModelManager, model, 'test.cto'); + const mf = new ModelFile(modelManager, model, 'test.cto'); mf.validate(); }).should.throw(); }); @@ -125,7 +106,7 @@ describe('ModelFile type parsing', () => { } `; (() => { - const mf = new ModelFile(mockModelManager, model, 'test.cto'); + const mf = new ModelFile(modelManager, model, 'test.cto'); mf.validate(); }).should.throw(); }); diff --git a/packages/concerto-core/test/logger.js b/packages/concerto-core/test/logger.js index edc21d644c..d8ada63de9 100644 --- a/packages/concerto-core/test/logger.js +++ b/packages/concerto-core/test/logger.js @@ -15,7 +15,6 @@ 'use strict'; const Logger = require('../lib/logger'); -const Fs = require('fs'); const Chai = require('chai'); Chai.should(); @@ -91,34 +90,49 @@ describe('logger', () => { }); }); }); - describe('#logger.info (in production)', function () { - it('should call logger.info', async function () { - process.env.NODE_ENV = 'production'; - Logger.info('This is logging some useful information'); + describe('#logger.verbose', function () { + it('should call logger.verbose', async function () { + Logger.verbose('This is logging some verbose message'); + }); + it('should call logger.verbose with an Error object', async function () { + Logger.verbose(new Error('This is some verbose message')); }); }); - describe('#setuplogger', () => { - const logDir = 'log'; - const logDirTest = 'logtest'; - it('should setup logger', async function () { - Logger.setup(process,'development',logDir); - }); - it('should setup logger (production)', async function () { - Logger.setup(process,'production',logDir); - }); - it('should setup logger with log directory', async function () { - Logger.setup(process,'development',logDirTest); - Fs.existsSync(logDir).should.be.true; - try { Fs.unlinkSync(`${logDirTest}/trace.log`); } catch (err) { Logger.info(err); } - try { Fs.rmdirSync(logDirTest, (err) => {}); } catch (err) { Logger.info(err); } - Logger.setup(process,'development',logDir); - }); - it('should setup logger with log directory (in production)', async function () { - Logger.setup(process,'production',logDirTest); - Fs.existsSync(logDir).should.be.true; - try { Fs.unlinkSync(`${logDirTest}/trace.log`); } catch (err) { Logger.info(err); } - try { Fs.rmdirSync(logDirTest, (err) => {}); } catch (err) { Logger.info(err); } - Logger.setup(process,'development',logDir); + describe('#logger.silly', function () { + it('should call logger.silly', async function () { + Logger.silly('This is logging some silly message'); + }); + it('should call logger.silly with an Error object', async function () { + Logger.silly(new Error('This is some silly message')); + }); + }); + describe('#logger.http', function () { + it('should call logger.http', async function () { + Logger.http('This is logging some http message'); + }); + it('should call logger.http with an Error object', async function () { + Logger.http(new Error('This is some http message')); + }); + }); + describe('#logger.dispatch', function () { + it('should fail to call logger.foo', async function () { + Logger.http('This is logging some http message'); + }); + it('should call logger.http with an Error object', async function () { + Logger.http(new Error('This is some http message')); + }); + }); + describe('#logger.add', function () { + it('should add a custom transport', async function () { + const messages = []; + Logger.add({ + info: (...args) => { + messages.push(args); + } + }); + Logger.info('This is logging to the default logger and my custom tranport'); + Logger.info(new Error('This is some silly message')); + messages.should.have.lengthOf(2); }); }); }); diff --git a/packages/concerto-core/test/model/concept-identified.js b/packages/concerto-core/test/model/concept-identified.js new file mode 100644 index 0000000000..25b30a9193 --- /dev/null +++ b/packages/concerto-core/test/model/concept-identified.js @@ -0,0 +1,111 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const ModelManager = require('../../lib/modelmanager'); +const Factory = require('../../lib/factory'); +const Identifiable = require('../../lib/model/identifiable'); +const chai = require('chai'); +chai.should(); +chai.use(require('chai-things')); + +describe('Concept Identifiers', function () { + + let modelManager; + let classDecl; + before(function () { + modelManager = new ModelManager(); + modelManager.addModelFile(`namespace org.accordproject + concept Address { + o String country + } + concept Product identified by sku { + o String sku + } + concept Order identified { + o Double ammount + o Address address + --> Product product + }`, 'test.cto'); + classDecl = modelManager.getType('org.accordproject.Order'); + }); + + beforeEach(function () { + }); + + afterEach(function () { + }); + + describe('#modelManager', function() { + it('should not parse a model with a relationship to a concept without an identifier', function () { + const temp = new ModelManager(); + (function () { + temp.addModelFile(`namespace org.accordproject + concept Address { + o String country + } + concept Order identified { + --> Address address + }`, 'invalid.cto'); + }).should.throw(/Relationship address must be to a class that has an identifier, but this is to org.accordproject.Address/); + }); + }); + + describe('#factory', function() { + it('should be able to create a relationship to a concept with an id', function () { + const factory = new Factory(modelManager); + const order = factory.newRelationship('org.accordproject', 'Order', '123'); + order.getIdentifier().should.equal('123'); + }); + + it('should not be able to create a relationship to a concept without an id', function () { + const factory = new Factory(modelManager); + (function () { + factory.newRelationship('org.accordproject', 'Address', '123'); + }).should.throw(/Cannot create a relationship to org.accordproject.Address, it is not identifiable./); + }); + + }); + + + describe('#toString', function() { + it('should be able to call toString', function () { + const id = new Identifiable(modelManager, classDecl, 'org.accordproject', 'Order', '123' ); + id.toString().should.equal('Identifiable {id=org.accordproject.Order#123}'); + }); + }); + + describe('#setIdentifier', () => { + it('should be able to set system identifier', function () { + const factory = new Factory(modelManager); + const order = factory.newResource('org.accordproject', 'Order', '123'); + order.getIdentifier().should.equal('123'); + order.$identifier.should.equal('123'); + order.setIdentifier('321'); + order.$identifier.should.equal('321'); + order.$identifier = 'ABC'; + order.getIdentifier().should.equal('ABC'); + }); + + it('should be able to set explicit identifier', function () { + const factory = new Factory(modelManager); + const product = factory.newResource('org.accordproject', 'Product', '123'); + product.getIdentifier().should.equal('123'); + product.sku.should.equal('123'); + product.setIdentifier('321'); + product.sku.should.equal('321'); + }); + }); +}); diff --git a/packages/concerto-core/test/model/concept.js b/packages/concerto-core/test/model/concept.js index ae17b13d9c..91dd1952b3 100644 --- a/packages/concerto-core/test/model/concept.js +++ b/packages/concerto-core/test/model/concept.js @@ -15,10 +15,10 @@ 'use strict'; const ModelManager = require('../../lib/modelmanager'); -const Concept = require('../../lib/model/concept'); +const Resource = require('../../lib/model/resource'); const Serializer = require('../../lib/serializer'); const Factory = require('../../lib/factory'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const fs = require('fs'); @@ -43,7 +43,7 @@ describe('Concept', function () { before(function () { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); }); beforeEach(function () { @@ -57,17 +57,16 @@ describe('Concept', function () { describe('#getClassDeclaration', function() { it('should return the class declaraction', function () { - const resource = new Concept(modelManager, classDecl, 'org.acme.l1', 'Person' ); + const resource = new Resource(modelManager, classDecl, 'org.acme.l1', 'Person' ); resource.getClassDeclaration().should.equal(classDecl); }); }); describe('#toJSON', () => { - it('should throw if toJSON is called', function () { - const resource = new Concept(modelManager, classDecl, 'org.acme.l1', 'Person'); - (function () { - resource.toJSON(); - }).should.throw(/Use Serializer.toJSON to convert resource instances to JSON objects./); + it('should call default toJSON', function () { + const resource = new Resource(modelManager, classDecl, 'org.acme.l1', 'Person', 'AAAA'); + resource.name = 'Dan'; + resource.toJSON().should.not.be.null; }); it('should generate JSON for an asset that contains a concept', function () { @@ -133,7 +132,7 @@ describe('Concept', function () { describe('#isConcept', () => { it('should be true', () => { - const resource = new Concept(modelManager, classDecl, 'org.acme.l1', 'Person'); + const resource = new Resource(modelManager, classDecl, 'org.acme.l1', 'Person'); resource.isConcept().should.be.true; }); }); diff --git a/packages/concerto-core/test/model/identifiable.js b/packages/concerto-core/test/model/identifiable.js index 5543822161..c9b6e866d3 100644 --- a/packages/concerto-core/test/model/identifiable.js +++ b/packages/concerto-core/test/model/identifiable.js @@ -20,7 +20,7 @@ const sinon = require('sinon'); const chai = require('chai'); chai.should(); chai.use(require('chai-things')); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); describe('Identifiable', function () { @@ -28,7 +28,7 @@ describe('Identifiable', function () { let classDecl; before(function () { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addModelFile(`namespace com.composer participant Farmer identified by farmerId { o String farmerId diff --git a/packages/concerto-core/test/model/relationship.js b/packages/concerto-core/test/model/relationship.js index 8d97245bc8..87694c95e1 100644 --- a/packages/concerto-core/test/model/relationship.js +++ b/packages/concerto-core/test/model/relationship.js @@ -16,7 +16,7 @@ const ModelManager = require('../../lib/modelmanager'); const Relationship = require('../../lib/model/relationship'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const chai = require('chai'); chai.should(); @@ -39,7 +39,7 @@ describe('Relationship', function () { before(function () { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); }); beforeEach(function () { diff --git a/packages/concerto-core/test/model/resource.js b/packages/concerto-core/test/model/resource.js index 8c8901142a..cb238e4b57 100644 --- a/packages/concerto-core/test/model/resource.js +++ b/packages/concerto-core/test/model/resource.js @@ -16,7 +16,7 @@ const ModelManager = require('../../lib/modelmanager'); const Resource = require('../../lib/model/resource'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); const chai = require('chai'); @@ -33,7 +33,8 @@ describe('Resource', function () { o String vin -->Person owner } - transaction ScrapCar { + transaction ScrapCar identified by transactionId { + o String transactionId -->Car car } `; @@ -42,7 +43,7 @@ describe('Resource', function () { beforeEach(function () { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addModelFile(levelOneModel); }); diff --git a/packages/concerto-core/test/model/typed.js b/packages/concerto-core/test/model/typed.js index ed8bf3955a..031ea8efee 100644 --- a/packages/concerto-core/test/model/typed.js +++ b/packages/concerto-core/test/model/typed.js @@ -16,7 +16,7 @@ const ModelManager = require('../../lib/modelmanager'); const Typed = require('../../lib/model/typed'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); require('chai').should(); @@ -30,7 +30,7 @@ describe('Typed', () => { beforeEach(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addModelFile(` namespace org.acme.base abstract asset BaseAsset { diff --git a/packages/concerto-core/test/model/validatedconcept.js b/packages/concerto-core/test/model/validatedconcept.js deleted file mode 100644 index d7b2d060e5..0000000000 --- a/packages/concerto-core/test/model/validatedconcept.js +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -const ModelManager = require('../../lib/modelmanager'); -const ValidatedConcept = require('../../lib/model/validatedconcept'); -const ResourceValidator = require('../../lib/serializer/resourcevalidator'); -const Util = require('../composer/systemmodelutility'); - -const sinon = require('sinon'); -const chai = require('chai'); -chai.should(); -chai.use(require('chai-things')); - -describe('ValidatedConcept', function () { - - const levelOneModel = `namespace org.acme.l1 - concept Person { - o String name - o String[] arrayName - } - asset Car identified by vin { - o String vin - o Person owner - } - `; - - let modelManager = null; - let classDecl = null; - let mockResourceValidator; - - before(function () { - modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); - }); - - beforeEach(function () { - modelManager.addModelFile(levelOneModel); - classDecl = modelManager.getType('org.acme.l1.Person'); - mockResourceValidator = sinon.createStubInstance(ResourceValidator); - mockResourceValidator.visit.returns(null); - - }); - - afterEach(function () { - modelManager.clearModelFiles(); - }); - - describe('#getClassDeclaration', function() { - it('should return the class declaraction', function () { - const resource = new ValidatedConcept(modelManager, classDecl, 'org.acme.l1', 'Person' ,mockResourceValidator); - resource.getClassDeclaration().should.equal(classDecl); - }); - }); - - describe('#setPropertyValue', () => { - it (' should accept valid property - value', function (){ - const resource = new ValidatedConcept(modelManager, classDecl, 'org.acme.l1', 'Person' ,mockResourceValidator); - resource.setPropertyValue('name','Fred Bloggs'); - }); - it (' should throw error for invalid property name', function (){ - const resource = new ValidatedConcept(modelManager, classDecl, 'org.acme.l1', 'Person' ,mockResourceValidator); - ( () => { - resource.setPropertyValue('namenamename','Fred Bloggs'); - }).should.throw(/Trying to set field namenamename which is not declared in the model/); - }); - it (' should throw error for array', function (){ - const resource = new ValidatedConcept(modelManager, classDecl, 'org.acme.l1', 'Person' ,mockResourceValidator); - ( () => { - resource.addArrayValue('name',['Fred','Bloggs']); - }).should.throw(/Trying to add array item name which is not declared as an array in the model/); - }); - it (' correct path for adding an array', function (){ - const resource = new ValidatedConcept(modelManager, classDecl, 'org.acme.l1', 'Person' ,mockResourceValidator); - resource.addArrayValue('arrayName',['Fred','Bloggs']); - }); - it (' should throw error for invalid property name', function (){ - const resource = new ValidatedConcept(modelManager, classDecl, 'org.acme.l1', 'Person' ,mockResourceValidator); - (()=>{ - resource.addArrayValue('invalid','Fred'); - }).should.throw(/Trying to set field invalid which is not declared in the model/); - }); - it (' validate', function (){ - const resource = new ValidatedConcept(modelManager, classDecl, 'org.acme.l1', 'Person' ,mockResourceValidator); - resource.validate(); - }); - it (' add two elements separately to an array property', function (){ - const resource = new ValidatedConcept(modelManager, classDecl, 'org.acme.l1', 'Person' ,mockResourceValidator); - resource.addArrayValue('arrayName','Fred'); - resource.addArrayValue('arrayName','Bloggs'); - }); - - }); - -}); diff --git a/packages/concerto-core/test/modelloader.js b/packages/concerto-core/test/modelloader.js index 33d8d0f236..e614fc2455 100644 --- a/packages/concerto-core/test/modelloader.js +++ b/packages/concerto-core/test/modelloader.js @@ -26,7 +26,7 @@ chai.use(require('chai-as-promised')); describe('ModelLoader', () => { - let modelBase = './test/data/model/model-base.cto'; + let modelBase = __dirname + '/data/model/model-base.cto'; let modelUrl = 'https://models.accordproject.org/patents/patent.cto'; beforeEach(() => { @@ -37,35 +37,35 @@ describe('ModelLoader', () => { describe('#loadModelManager', function() { it('should load models', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); (function() { modelManager.getType('String'); }).should.throw(TypeNotFoundException); }); it('should throw an error for a namespace that does not exist', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); (function() { modelManager.getType('org.acme.nosuchns.SimpleAsset'); }).should.throw(TypeNotFoundException, /org.acme.nosuchns/); }); it('should throw an error for an empty namespace', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); (function() { modelManager.getType('NoSuchAsset'); }).should.throw(TypeNotFoundException, /NoSuchAsset/); }); it('should throw an error for a type that does not exist', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); (function() { modelManager.getType('org.acme.base.NoSuchAsset'); }).should.throw(TypeNotFoundException, /NoSuchAsset/); }); it('should return the class declaration for a valid type', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); const declaration = modelManager.getType('org.acme.base.AbstractAsset'); declaration.getFullyQualifiedName().should.equal('org.acme.base.AbstractAsset'); }); @@ -73,51 +73,47 @@ describe('ModelLoader', () => { describe('#loadModelManagerFromModelFiles', function() { it('should load models', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); const files = modelManager.getModelFiles() - .filter(f => !f.isSystemModelFile()) .map(f => f.definitions); - const modelManager2 = await ModelLoader.loadModelManagerFromModelFiles(null, files); + const modelManager2 = await ModelLoader.loadModelManagerFromModelFiles(files); (function() { modelManager2.getType('String'); }).should.throw(TypeNotFoundException); }); it('should throw an error for a namespace that does not exist', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); const files = modelManager.getModelFiles() - .filter(f => !f.isSystemModelFile()) .map(f => f.definitions); - const modelManager2 = await ModelLoader.loadModelManagerFromModelFiles(null, files); + const modelManager2 = await ModelLoader.loadModelManagerFromModelFiles(files); (function() { modelManager2.getType('org.acme.nosuchns.SimpleAsset'); }).should.throw(TypeNotFoundException, /org.acme.nosuchns/); }); it('should throw an error for an empty namespace', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); const files = modelManager.getModelFiles() - .filter(f => !f.isSystemModelFile()) .map(f => f.definitions); - const modelManager2 = await ModelLoader.loadModelManagerFromModelFiles(null, files); + const modelManager2 = await ModelLoader.loadModelManagerFromModelFiles(files); (function() { modelManager2.getType('NoSuchAsset'); }).should.throw(TypeNotFoundException, /NoSuchAsset/); }); it('should throw an error for a type that does not exist', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); const files = modelManager.getModelFiles() - .filter(f => !f.isSystemModelFile()) .map(f => f.definitions); - const modelManager2 = await ModelLoader.loadModelManagerFromModelFiles(null, files); + const modelManager2 = await ModelLoader.loadModelManagerFromModelFiles(files); (function() { modelManager2.getType('org.acme.base.NoSuchAsset'); }).should.throw(TypeNotFoundException, /NoSuchAsset/); }); it('should return the class declaration for a valid type', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); const declaration = modelManager.getType('org.acme.base.AbstractAsset'); declaration.getFullyQualifiedName().should.equal('org.acme.base.AbstractAsset'); }); @@ -125,7 +121,7 @@ describe('ModelLoader', () => { describe('#loadModelFromUrl', function() { it('should load models', async function() { - const modelManager = await ModelLoader.loadModelManager(null, [modelUrl]); + const modelManager = await ModelLoader.loadModelManager([modelUrl]); (modelManager instanceof ModelManager).should.be.true; }); }); @@ -133,7 +129,7 @@ describe('ModelLoader', () => { describe('#getFactory', () => { it('should return a factory', async () => { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); modelManager.getFactory().should.be.an.instanceOf(Factory); }); @@ -142,7 +138,7 @@ describe('ModelLoader', () => { describe('#getSerializer', () => { it('should return a serializer', async () => { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); modelManager.getSerializer().should.be.an.instanceOf(Serializer); }); @@ -150,7 +146,7 @@ describe('ModelLoader', () => { describe('#hasInstance', () => { it('should return true for a valid ModelManager', async () => { - const modelManager = await ModelLoader.loadModelManager(null, [modelBase]); + const modelManager = await ModelLoader.loadModelManager([modelBase]); (modelManager instanceof ModelManager).should.be.true; }); }); diff --git a/packages/concerto-core/test/modelmanager.js b/packages/concerto-core/test/modelmanager.js index 8d70c68634..93a0b84e52 100644 --- a/packages/concerto-core/test/modelmanager.js +++ b/packages/concerto-core/test/modelmanager.js @@ -27,10 +27,9 @@ const ModelFileDownloader = require('../lib/introspect/loaders/modelfiledownload const ModelManager = require('../lib/modelmanager'); const ParticipantDeclaration = require('../lib/introspect/participantdeclaration'); const Serializer = require('../lib/serializer'); -const TransactionDeclaration = require('../lib/introspect/transactiondeclaration'); const TypeNotFoundException = require('../lib/typenotfoundexception'); -const ModelUtil = require('../lib/modelutil'); -const Util = require('./composer/systemmodelutility'); +const Util = require('./composer/composermodelutility'); +const COMPOSER_MODEL = require('./composer/composermodel'); const chai = require('chai'); const should = chai.should(); @@ -47,17 +46,12 @@ describe('ModelManager', () => { let invalidModel = fs.readFileSync('./test/data/model/invalid.cto', 'utf8'); let invalidModel2 = fs.readFileSync('./test/data/model/invalid2.cto', 'utf8'); let modelManager; - let mockSystemModelFile; let sandbox; beforeEach(() => { sandbox = sinon.createSandbox(); modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); - mockSystemModelFile = sinon.createStubInstance(ModelFile); - mockSystemModelFile.isLocalType.withArgs('Asset').returns(true); - mockSystemModelFile.getNamespace.returns('org.hyperledger.composer.system'); - mockSystemModelFile.isSystemModelFile.returns(true); + Util.addComposerModel(modelManager); }); afterEach(() => { @@ -139,15 +133,6 @@ describe('ModelManager', () => { res.should.equal(mf1); }); - it('should not be possible to add a system model file explicit system model table', ()=>{ - let mf1 = sinon.createStubInstance(ModelFile); - mf1.getNamespace.returns('org.doge'); - let res = modelManager.addModelFile(mf1, null, null, ModelUtil.getIdentitySystemModelTable()); - sinon.assert.calledOnce(mf1.validate); - modelManager.modelFiles['org.doge'].should.equal(mf1); - res.should.equal(mf1); - }); - it('should return error for duplicate namespaces for a string', () => { modelManager.addModelFile(modelBase); let mf1 = sinon.createStubInstance(ModelFile); @@ -262,9 +247,7 @@ describe('ModelManager', () => { } modelManager.getModelFile('org.acme.base').getNamespace().should.equal('org.acme.base'); - modelManager.getModelFiles().filter((modelFile) => { - return !modelFile.isSystemModelFile(); - }).length.should.equal(1); + modelManager.getModelFiles().length.should.equal(2); }); it('should restore existing model files on validation error', () => { @@ -285,24 +268,6 @@ describe('ModelManager', () => { should.equal(modelManager.modelFiles['org.fry'], undefined); }); - it('should not be possible to add a system model file', ()=>{ - (() => { - modelManager.addModelFiles([mockSystemModelFile]); - }).should.throw(); - }); - - it('should not be possible to add a system model file (via string)', ()=>{ - (() => { - modelManager.addModelFiles(['namespace org.hyperledger.composer.system'],['fakesysnamespace.cto'], null, true); - }).should.throw(/System namespace can not be updated/); - }); - - it('should not be possible to add a system model file (via string) with explicit system model table', ()=>{ - (() => { - modelManager.addModelFiles(['namespace org.hyperledger.composer.system'],['fakesysnamespace.cto'], null, ModelUtil.getIdentitySystemModelTable()); - }).should.throw(/System namespace can not be updated/); - }); - it('should return an error for duplicate namespace from strings', () => { (() => { modelManager.addModelFiles([composerModel, modelBase, farm2fork, modelBase]); @@ -354,7 +319,7 @@ describe('ModelManager', () => { }`; (() => { modelManager.addModelFiles([mf1, mf2]); - }).should.throw(/Expected.* Line 2 column 27/); + }).should.throw(/Expected.* Line 2 column 47/); }); it('should return the error message for an invalid model file with a file name', () => { @@ -368,7 +333,7 @@ describe('ModelManager', () => { }`; (() => { modelManager.addModelFiles([mf1, mf2], ['mf1.cto', 'mf2.cto']); - }).should.throw(/Expected.* File mf2.cto line 2 column 27/); + }).should.throw(/Expected.* File mf2.cto line 2 column 47/); }); it('should handle model files with assets passed in the wrong logical order', () => { @@ -426,14 +391,14 @@ describe('ModelManager', () => { mf1.getNamespace.returns('org.doge'); (() => { modelManager.updateModelFile(mf1); - }).should.throw(/model file does not exist/); + }).should.throw(/Model file for namespace org.doge not found/); }); it('throw if the namespace from a string does not exist', () => { let model = 'namespace org.doge\nasset TestAsset identified by assetId { o String assetId }'; (() => { modelManager.updateModelFile(model); - }).should.throw(/model file does not exist/); + }).should.throw(/Model file for namespace org.doge not found/); }); it('should update from an object', () => { @@ -496,19 +461,6 @@ describe('ModelManager', () => { modelManager.modelFiles['org.doge'].definitions.should.equal(model); }); - it('should not be possible to update a system model file', ()=>{ - (() => { - modelManager.updateModelFile(mockSystemModelFile); - }).should.throw(); - }); - - it('should not be possible to update a system model file (via string)', ()=>{ - (() => { - modelManager.updateModelFile('namespace org.hyperledger.composer.system','fakesysnamespace.cto'); - }).should.throw(); - }); - - }); describe('#deleteModelFile', () => { @@ -518,7 +470,7 @@ describe('ModelManager', () => { mf1.getNamespace.returns('org.doge'); (() => { modelManager.deleteModelFile(mf1); - }).should.throw(/model file does not exist/); + }).should.throw(/Model file does not exist/); }); it('delete the model file', () => { @@ -532,13 +484,6 @@ describe('ModelManager', () => { modelManager.deleteModelFile('org.doge'); should.equal(modelManager.modelFiles['org.doge'], undefined); }); - - it('should not be possible to delete a system model file', ()=>{ - (() => { - modelManager.deleteModelFile('org.hyperledger.composer.system'); - }).should.throw(/Cannot delete system namespace/); - }); - }); describe('#updateExternalModels', () => { @@ -686,6 +631,7 @@ concept Bar { fs.readdirSync(dir.path).should.eql([ '@external.cto', 'internal.cto', + 'system.cto', ]); dir.cleanup(); }); @@ -697,19 +643,19 @@ concept Bar { }); fs.readdirSync(dir.path).should.eql([ 'internal.cto', + 'system.cto', ]); dir.cleanup(); }); - it('should write models to the file system, with system models', async () => { + it('should write models to the file system', async () => { const dir = await tmp.dir({ unsafeCleanup: true}); modelManager.writeModelsToFileSystem(dir.path, { - includeSystemModels: true }); fs.readdirSync(dir.path).should.eql([ '@external.cto', 'internal.cto', - 'org.hyperledger.composer.system.cto' + 'system.cto' ]); dir.cleanup(); }); @@ -719,30 +665,17 @@ concept Bar { }); }); - describe('#getSystemModelFiles', () => { - it('should only list all system model files', () => { - modelManager.addModelFile(modelBase); - modelManager.getModelFiles().length.should.equal(2); - modelManager.getSystemModelFiles().length.should.equal(1); - }); - }); - describe('#getModels', () => { it('should return a list of name / content pairs', () => { modelManager.addModelFile(modelBase); const models = modelManager.getModels(); - models.length.should.equal(1); + models.length.should.equal(2); models[0].should.deep.equal({ + name: 'system.cto', content: COMPOSER_MODEL.contents + }, { name: 'org.acme.base.cto', content: modelBase }); }); - it('should return a list of name / content pairs, with System Models', () => { - modelManager.addModelFile(modelBase); - const models = modelManager.getModels({ - includeSystemModels: true - }); - models.length.should.equal(2); - }); it('should return a list of name / content pairs, with External Models', async () => { const externalModelFile = new ModelFile(modelManager, `namespace org.external concept Foo{ o String baz }`, '@external.cto'); @@ -762,7 +695,7 @@ concept Bar { const options = {}; await modelManager.updateExternalModels(options, mfd); const models = modelManager.getModels(); - models.length.should.equal(2); + models.length.should.equal(3); }); it('should return a list of name / content pairs, without External Models', async () => { @@ -786,7 +719,7 @@ concept Bar { const models = modelManager.getModels({ includeExternalModels: false }); - models.length.should.equal(1); + models.length.should.equal(2); }); }); @@ -806,177 +739,54 @@ concept Bar { }); - describe('#getSystemTypes', () => { - - it('should return all of the system core types', () => { - modelManager.getSystemTypes().map((classDeclaration) => { - return classDeclaration.getName(); - }).should.deep.equal(['Asset', 'Participant', 'Transaction', 'Event']); - }); - - }); - describe('#getDeclarations', () => { - - const numberSystemAssets = 8; - const numberSystemEnums = 1; - const numberSystemParticipants = 2; - const numberSystemEvents = 1; - const numberSystemTransactions = 17; - const numberSystemConcepts = 0; - - const numberModelBaseAssets = 5; - const numberModelBaseEnums = 1; - const numberModelBaseParticipants = 2; - const numberModelBaseEvents = 0; - const numberModelBaseTransactions = 3; + const numberModelBaseAssets = 13; + const numberModelBaseEnums = 2; + const numberModelBaseParticipants = 5; + const numberModelBaseEvents = 1; + const numberModelBaseTransactions = 21; const numberModelBaseConcepts = 2; - describe('#getAssetDeclarations', () => { - it('should return all of the asset declarations with system types', () => { + it('should return all of the asset declarations', () => { modelManager.addModelFile(modelBase); let decls = modelManager.getAssetDeclarations(); decls.should.all.be.an.instanceOf(AssetDeclaration); - decls.length.should.equal(numberSystemAssets+numberModelBaseAssets); - }); - - }); - - describe('#getAssetDeclarationsWithParameterFalse', () => { - - it('should return all of the asset declarations without system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getAssetDeclarations(false); - decls.should.all.be.an.instanceOf(AssetDeclaration); decls.length.should.equal(numberModelBaseAssets); - let i; - for(i = 0; i < decls.length; i++) { - decls[i].modelFile.should.have.property('systemModelFile', false); - } - }); - - }); - - describe('#getAssetDeclarationsWithParameterTrue', () => { - - it('should return all of the asset declarations with system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getAssetDeclarations(true); - decls.should.all.be.an.instanceOf(AssetDeclaration); - decls.length.should.equal(numberSystemAssets+numberModelBaseAssets); }); }); describe('#getEnumDeclarations', () => { - it('should return all of the enum declarations with system types', () => { + it('should return all of the enum declarations', () => { modelManager.addModelFile(modelBase); let decls = modelManager.getEnumDeclarations(); decls.should.all.be.an.instanceOf(EnumDeclaration); - decls.length.should.equal(numberSystemEnums+numberModelBaseEnums); - }); - - }); - - describe('#getEnumDeclarationsWithParameterFalse', () => { - - it('should return all of the enum declarations without system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getEnumDeclarations(false); - decls.should.all.be.an.instanceOf(EnumDeclaration); decls.length.should.equal(numberModelBaseEnums); - let i; - for(i = 0; i < decls.length; i++) { - decls[i].modelFile.should.have.property('systemModelFile', false); - } - }); - - }); - - describe('#getEnumDeclarationsWithParameterTrue', () => { - - it('should return all of the enum declarations with system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getEnumDeclarations(true); - decls.should.all.be.an.instanceOf(EnumDeclaration); - decls.length.should.equal(numberSystemEnums+numberModelBaseEnums); }); }); describe('#getParticipantDeclarations', () => { - it('should return all of the participant declarations with system types', () => { + it('should return all of the participant declarations', () => { modelManager.addModelFile(modelBase); let decls = modelManager.getParticipantDeclarations(); decls.should.all.be.an.instanceOf(ParticipantDeclaration); - decls.length.should.equal(numberSystemParticipants+numberModelBaseParticipants); - }); - - }); - - describe('#getParticipantDeclarationsWithParameterFalse', () => { - - it('should return all of the participant declarations without system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getParticipantDeclarations(false); - decls.should.all.be.an.instanceOf(ParticipantDeclaration); decls.length.should.equal(numberModelBaseParticipants); - let i; - for(i = 0; i < decls.length; i++) { - decls[i].modelFile.should.have.property('systemModelFile', false); - } - }); - - }); - - describe('#getParticipantDeclarationsWithParameterTrue', () => { - - it('should return all of the participant declarations with system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getParticipantDeclarations(true); - decls.should.all.be.an.instanceOf(ParticipantDeclaration); - decls.length.should.equal(numberSystemParticipants+numberModelBaseParticipants); }); }); describe('#getEventDeclarations', () => { - it('should return all of the event declarations with system types', () => { + it('should return all of the event declarations', () => { modelManager.addModelFile(modelBase); let decls = modelManager.getEventDeclarations(); decls.should.all.be.an.instanceOf(EventDeclaration); - decls.length.should.equal(numberSystemEvents+numberModelBaseEvents); - }); - - }); - - describe('#getEventDeclarationsWithParameterFalse', () => { - - it('should return all of the event declarations without system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getEventDeclarations(false); - decls.should.all.be.an.instanceOf(EventDeclaration); decls.length.should.equal(numberModelBaseEvents); - let i; - for(i = 0; i < decls.length; i++) { - decls[i].modelFile.should.have.property('systemModelFile', false); - } - }); - - }); - - describe('#getEventDeclarationsWithParameterTrue', () => { - - it('should return all of the event declarations with system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getEventDeclarations(true); - decls.should.all.be.an.instanceOf(EventDeclaration); - decls.length.should.equal(numberSystemEvents+numberModelBaseEvents); }); }); @@ -986,33 +796,7 @@ concept Bar { it('should return all of the transaction declarations', () => { modelManager.addModelFile(modelBase); let decls = modelManager.getTransactionDeclarations(); - decls.length.should.equal(numberSystemTransactions+numberModelBaseTransactions); - }); - - }); - - describe('#getTransactionDeclarationsWithParameterFalse', () => { - - it('should return all of the transaction declarations without system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getTransactionDeclarations(false); - decls.should.all.be.an.instanceOf(TransactionDeclaration); decls.length.should.equal(numberModelBaseTransactions); - let i; - for(i = 0; i < decls.length; i++) { - decls[i].modelFile.should.have.property('systemModelFile', false); - } - }); - - }); - - describe('#getTransactionDeclarationsWithParameterTrue', () => { - - it('should return all of the transaction declarations with system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getTransactionDeclarations(true); - decls.should.all.be.an.instanceOf(TransactionDeclaration); - decls.length.should.equal(numberSystemTransactions+numberModelBaseTransactions); }); }); @@ -1023,34 +807,8 @@ concept Bar { modelManager.addModelFile(modelBase); let decls = modelManager.getConceptDeclarations(); decls.should.all.be.an.instanceOf(ConceptDeclaration); - decls.length.should.equal(numberSystemConcepts+numberModelBaseConcepts); - }); - }); - - describe('#getConceptDeclarationsWithParameterFalse', () => { - - it('should return all of the concept declarations without system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getConceptDeclarations(false); - decls.should.all.be.an.instanceOf(ConceptDeclaration); decls.length.should.equal(numberModelBaseConcepts); - let i; - for(i = 0; i < decls.length; i++) { - decls[i].modelFile.should.have.property('systemModelFile', false); - } }); - - }); - - describe('#getConceptDeclarationsWithParameterTrue', () => { - - it('should return all of the concept declarations with system types', () => { - modelManager.addModelFile(modelBase); - let decls = modelManager.getConceptDeclarations(true); - decls.should.all.be.an.instanceOf(ConceptDeclaration); - decls.length.should.equal(numberSystemConcepts+numberModelBaseConcepts); - }); - }); }); diff --git a/packages/concerto-core/test/models/animaltracking.js b/packages/concerto-core/test/models/animaltracking.js index 23948a3f51..d085b474dc 100644 --- a/packages/concerto-core/test/models/animaltracking.js +++ b/packages/concerto-core/test/models/animaltracking.js @@ -23,7 +23,7 @@ const Relationship = require('../../lib/model/relationship'); const RelationshipDeclaration = require('../../lib/introspect/relationshipdeclaration'); const Serializer = require('../../lib/serializer'); const fs = require('fs'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); describe('animaltracking Model', function(){ @@ -35,7 +35,7 @@ describe('animaltracking Model', function(){ beforeEach(function(){ modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; animaltrackingModel = fs.readFileSync('./test/data/model/animaltracking.cto', 'utf8'); diff --git a/packages/concerto-core/test/models/customsystem.js b/packages/concerto-core/test/models/customsystem.js deleted file mode 100644 index 4ee7499ece..0000000000 --- a/packages/concerto-core/test/models/customsystem.js +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -require('chai').should(); -const ModelManager = require('../../lib/modelmanager'); - -const fs = require('fs'); - -describe('Custom System Model', function() { - describe('#getModelManagerCustomSystem', function() { - it('check parsing and model manager', function() { - let modelManager = new ModelManager(); - modelManager.should.not.be.null; - - const table = new Map(); - table.set('MyTransaction', 'Transaction'); - table.set('MyAsset', 'Asset'); - table.set('MyEvent', 'Event'); - table.set('MyParticipant', 'Participant'); - - // parse a model file from disk and add to the ModelManager - let fileName = './test/data/model/customsystem-base.cto'; - let systemModel = fs.readFileSync(fileName, 'utf8'); - systemModel.should.not.be.null; - modelManager.addModelFile(systemModel,fileName, false, table); - - fileName = './test/data/model/customsystem-extends.cto'; - let file = fs.readFileSync(fileName, 'utf8'); - file.should.not.be.null; - modelManager.addModelFile(file,fileName); - modelManager.getModelFiles().filter((modelFile) => { - return !modelFile.isSystemModelFile(); - }).length.should.equal(1); - - let systemModelFile = modelManager.getModelFile('org.hyperledger.composer.customsystem'); - systemModelFile.getNamespace().should.equal('org.hyperledger.composer.customsystem'); - systemModelFile.getAssetDeclarations().length.should.equal(1); - systemModelFile.getTransactionDeclarations().length.should.equal(1); - systemModelFile.getEventDeclarations().length.should.equal(1); - systemModelFile.getParticipantDeclarations().length.should.equal(1); - - let myAsset = systemModelFile.getAssetDeclaration('MyAsset'); - (myAsset.getSuperType()=== null).should.be.true; - myAsset.isSystemType().should.be.true; - myAsset.isSystemCoreType().should.be.true; - myAsset.getSystemType().should.equal('MyAsset'); - - let modelFile = modelManager.getModelFile('org.acme'); - modelFile.getNamespace().should.equal('org.acme'); - modelFile.getAssetDeclarations().length.should.equal(1); - modelFile.getTransactionDeclarations().length.should.equal(1); - modelFile.getEventDeclarations().length.should.equal(1); - modelFile.getParticipantDeclarations().length.should.equal(1); - - // test the YourAsset Asset class - let yourAsset = modelFile.getAssetDeclaration('YourAsset'); - yourAsset.should.not.be.null; - yourAsset.getIdentifierFieldName().should.equal('myAssetId'); - yourAsset.getProperties().length.should.equal(1); - yourAsset.getSystemType().should.equal('MyAsset'); - - // validator, default - let identifierField = yourAsset.getProperty('myAssetId'); - (identifierField.getType() === 'String').should.be.true; - identifierField.getName().should.equal('myAssetId'); - (identifierField.getDefaultValue() === null).should.be.true; - identifierField.isOptional().should.be.false; - - }); - }); -}); diff --git a/packages/concerto-core/test/models/dependencies2.js b/packages/concerto-core/test/models/dependencies2.js index e17238f2cc..65383265e4 100644 --- a/packages/concerto-core/test/models/dependencies2.js +++ b/packages/concerto-core/test/models/dependencies2.js @@ -19,13 +19,13 @@ const ModelManager = require('../../lib/modelmanager'); const Factory = require('../../lib/factory'); const Serializer = require('../../lib/serializer'); const fs = require('fs'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); describe('Dependencies2 Model', function() { describe('#model', function() { it('create instance', function() { let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; // parse a model file from disk and add to the ModelManager diff --git a/packages/concerto-core/test/models/farm2fork.js b/packages/concerto-core/test/models/farm2fork.js index 1fe66fca35..ce3f112723 100644 --- a/packages/concerto-core/test/models/farm2fork.js +++ b/packages/concerto-core/test/models/farm2fork.js @@ -17,7 +17,7 @@ require('chai').should(); const ModelManager = require('../../lib/modelmanager'); const RelationshipDeclaration = require('../../lib/introspect/relationshipdeclaration'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const fs = require('fs'); @@ -25,7 +25,7 @@ describe('Farm2Fork Model', function() { describe('#getModelManagerFarm2Fork', function() { it('check parsing and model manager', function() { let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; // parse a model file from disk and add to the ModelManager @@ -38,9 +38,7 @@ describe('Farm2Fork Model', function() { let file = fs.readFileSync(fileName, 'utf8'); file.should.not.be.null; modelManager.addModelFile(file,fileName); - modelManager.getModelFiles().filter((modelFile) => { - return !modelFile.isSystemModelFile(); - }).length.should.equal(2); + modelManager.getModelFiles().length.should.equal(3); let modelFile = modelManager.getModelFile('org.acme'); modelFile.getNamespace().should.equal('org.acme'); diff --git a/packages/concerto-core/test/models/model.js b/packages/concerto-core/test/models/model.js index efa6126bea..3f8f75c1f2 100644 --- a/packages/concerto-core/test/models/model.js +++ b/packages/concerto-core/test/models/model.js @@ -17,7 +17,7 @@ const Factory = require('../../lib/factory'); const ModelManager = require('../../lib/modelmanager'); const Serializer = require('../../lib/serializer'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); const assert = require('assert'); @@ -29,7 +29,7 @@ describe('Model Tests', function(){ describe('#validation', function() { it('check property validation', function() { const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; modelManager.clearModelFiles(); diff --git a/packages/concerto-core/test/models/nosystemmodels.js b/packages/concerto-core/test/models/nosystemmodels.js deleted file mode 100644 index 71433a0c99..0000000000 --- a/packages/concerto-core/test/models/nosystemmodels.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -require('chai').should(); -const ModelManager = require('../../lib/modelmanager'); - -const fs = require('fs'); - -describe('No System Models', function() { - describe('#getModelManager', function() { - it('check parsing and model manager', function() { - let modelManager = new ModelManager(); - modelManager.should.not.be.null; - - // parse a model file from disk and add to the ModelManager - let fileName = './test/data/model/carlease-nosystem.cto'; - let carLeaseModel = fs.readFileSync(fileName, 'utf8'); - carLeaseModel.should.not.be.null; - modelManager.addModelFile(carLeaseModel,fileName); - - let carLeaseModelFile = modelManager.getModelFile('org.acme'); - carLeaseModelFile.getNamespace().should.equal('org.acme'); - carLeaseModelFile.getAssetDeclarations().length.should.equal(2); - carLeaseModelFile.getTransactionDeclarations().length.should.equal(3); - carLeaseModelFile.getEventDeclarations().length.should.equal(1); - carLeaseModelFile.getParticipantDeclarations().length.should.equal(2); - }); - }); -}); diff --git a/packages/concerto-core/test/models/relationship.js b/packages/concerto-core/test/models/relationship.js index 124e6c407e..0c0b8fc8cb 100644 --- a/packages/concerto-core/test/models/relationship.js +++ b/packages/concerto-core/test/models/relationship.js @@ -18,14 +18,14 @@ const assert = require('assert'); require('chai').should(); const fs = require('fs'); const ModelManager = require('../../lib/modelmanager'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); describe('Test Relationships', function(){ describe('#validate', function() { it('check that relationships to primitives are illegal', function() { // create and populate the ModelManager with a model file const modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; modelManager.clearModelFiles(); diff --git a/packages/concerto-core/test/models/test.js b/packages/concerto-core/test/models/test.js index 7ba449c923..7e48595d06 100644 --- a/packages/concerto-core/test/models/test.js +++ b/packages/concerto-core/test/models/test.js @@ -21,7 +21,7 @@ const RelationshipDeclaration = require('../../lib/introspect/relationshipdeclar const Serializer = require('../../lib/serializer'); const TypeNotFoundException = require('../../lib/typenotfoundexception'); const fs = require('fs'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); require('chai').should(); @@ -33,7 +33,7 @@ describe('Test Model', function(){ // create and populate the ModelManager with a model file let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; modelManager.clearModelFiles(); @@ -72,7 +72,7 @@ describe('Test Model', function(){ // create and populate the ModelManager with a model file let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; modelManager.clearModelFiles(); @@ -140,7 +140,7 @@ describe('Test Model', function(){ // create and populate the ModelManager with a model file let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; modelManager.clearModelFiles(); @@ -225,7 +225,7 @@ describe('Test Model', function(){ describe('#getModelManager', function() { it('check parsing and model manager', function() { let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; let fileName1 = './test/data/model/composer.cto'; @@ -243,9 +243,7 @@ describe('Test Model', function(){ // check the clear modelManager.clearModelFiles(); - modelManager.getModelFiles().filter((modelFile) => { - return !modelFile.isSystemModelFile(); - }).length.should.equal(0); + modelManager.getModelFiles().length.should.equal(0); // the system model will remain hence 1. // re-add @@ -321,7 +319,7 @@ describe('Test Model', function(){ // create and populate the ModelManager with a model file let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let fileName = './test/data/model/composer.cto'; let systemModel = fs.readFileSync(fileName, 'utf8'); @@ -338,10 +336,9 @@ describe('Test Model', function(){ modelFile.isImportedType('MyParticipant').should.equal(true); let imprts = modelFile.getImports().filter( (element) => { const importNamespace = ModelUtil.getNamespace(element); - const modelFile = modelManager.getModelFile(importNamespace); - return !modelFile.isSystemModelFile(); + return modelManager.getModelFile(importNamespace); }); - imprts.length.should.equal(1); + imprts.length.should.equal(2); modelFile.getImports().includes('composer.MyParticipant').should.equal(true); }); }); @@ -351,7 +348,7 @@ describe('Test Model', function(){ // create and populate the ModelManager with a model file let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); let fileName = './test/data/model/dependencies/base/base.cto'; let baseModel = fs.readFileSync(fileName, 'utf8'); @@ -378,10 +375,9 @@ describe('Test Model', function(){ modelFile.isImportedType('Person').should.equal(true); let imprts = modelFile.getImports().filter( (element) => { const importNamespace = ModelUtil.getNamespace(element); - const modelFile = modelManager.getModelFile(importNamespace); - return !modelFile.isSystemModelFile(); + return modelManager.getModelFile(importNamespace); }); - imprts.length.should.equal(2); + imprts.length.should.equal(3); }); }); }); diff --git a/packages/concerto-core/test/models/vehicle-lifecycle.js b/packages/concerto-core/test/models/vehicle-lifecycle.js index 3433d2b9db..b09a0c5b9f 100644 --- a/packages/concerto-core/test/models/vehicle-lifecycle.js +++ b/packages/concerto-core/test/models/vehicle-lifecycle.js @@ -19,13 +19,13 @@ const ModelManager = require('../../lib/modelmanager'); const Factory = require('../../lib/factory'); const Serializer = require('../../lib/serializer'); const fs = require('fs'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); describe('Vehicle-Lifecycle Model', function() { describe('#model validation', function() { it('check create complex resource and roundtrip to JSON', function() { let modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.should.not.be.null; // parse a model file from disk and add to the ModelManager diff --git a/packages/concerto-core/test/models/wildcards.js b/packages/concerto-core/test/models/wildcards.js index 84aa87603b..e7ed7ce054 100644 --- a/packages/concerto-core/test/models/wildcards.js +++ b/packages/concerto-core/test/models/wildcards.js @@ -18,7 +18,7 @@ const Factory = require('../../lib/factory'); const fs = require('fs'); const ModelManager = require('../../lib/modelmanager'); const Serializer = require('../../lib/serializer'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); require('chai').should(); @@ -31,7 +31,7 @@ describe('Wildcards Model', function () { beforeEach(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); factory = new Factory(modelManager); serializer = new Serializer(factory, modelManager); ergoSerializer = new Serializer(factory, modelManager); @@ -60,7 +60,7 @@ describe('Wildcards Model', function () { }, participant: { $class: 'org.acme.wildcards.MyParticipant', - participantId: '1', + personId: '1', firstName: 'Alice', lastName: 'A', contactDetails: { @@ -73,7 +73,7 @@ describe('Wildcards Model', function () { const resource = serializer.fromJSON(json); resource.assetId.should.equal('1'); resource.concept.gender.should.equal('FEMALE'); - resource.participant.participantId.should.equal('1'); + resource.participant.personId.should.equal('1'); resource.participant.firstName.should.equal('Alice'); resource.participant.lastName.should.equal('A'); resource.participant.contactDetails.email.should.equal('alice@email.com'); @@ -86,11 +86,11 @@ describe('Wildcards Model', function () { assetId: '1', concept: { $class: 'org.acme.wildcards.MyConcept', - gender: { 'type': 'stdlib.base.Gender', 'data': { 'right' : { 'left': 'FEMALE' } } } + gender: { '$class': 'stdlib.base.Gender', '$data': { '$right' : { '$left': 'FEMALE' } } } }, participant: { $class: 'org.acme.wildcards.MyParticipant', - participantId: '1', + personId: '1', firstName: 'Alice', lastName: 'A', contactDetails: { @@ -103,7 +103,7 @@ describe('Wildcards Model', function () { const resource = ergoSerializer.fromJSON(json); resource.assetId.should.equal('1'); resource.concept.gender.should.equal('FEMALE'); - resource.participant.participantId.should.equal('1'); + resource.participant.personId.should.equal('1'); resource.participant.firstName.should.equal('Alice'); resource.participant.lastName.should.equal('A'); resource.participant.contactDetails.email.should.equal('alice@email.com'); @@ -131,7 +131,7 @@ describe('Wildcards Model', function () { }, participant: { $class: 'org.acme.wildcards.MyParticipant', - participantId: '1', + personId: '1', firstName: 'Alice', lastName: 'A', contactDetails: { diff --git a/packages/concerto-core/test/modelutil.js b/packages/concerto-core/test/modelutil.js index deb94c2389..719f591ce9 100644 --- a/packages/concerto-core/test/modelutil.js +++ b/packages/concerto-core/test/modelutil.js @@ -19,7 +19,7 @@ const Property = require('../lib/introspect/property'); const Typed = require('../lib/model/identifiable'); const ModelManager = require('../lib/modelmanager'); const ModelUtil = require('../lib/modelutil'); -const Util = require('./composer/systemmodelutility'); +const Util = require('./composer/composermodelutility'); require('chai').should(); const sinon = require('sinon'); @@ -115,7 +115,7 @@ describe('ModelUtil', function () { beforeEach(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addModelFile(`namespace org.acme.baz asset Foo identified by fooId { o String fooId diff --git a/packages/concerto-core/test/serializer.js b/packages/concerto-core/test/serializer.js index 5fdf5685f0..97283f1d8a 100644 --- a/packages/concerto-core/test/serializer.js +++ b/packages/concerto-core/test/serializer.js @@ -18,10 +18,9 @@ const Factory = require('../lib/factory'); const ModelManager = require('../lib/modelmanager'); const Relationship = require('../lib/model/relationship'); const Resource = require('../lib/model/resource'); -const Concept = require('../lib/model/concept'); const Serializer = require('../lib/serializer'); const TypeNotFoundException = require('../lib/typenotfoundexception'); -const Util = require('./composer/systemmodelutility'); +const Util = require('./composer/composermodelutility'); const should = require('chai').should(); const sinon = require('sinon'); @@ -37,7 +36,7 @@ describe('Serializer', () => { sandbox = sinon.createSandbox(); modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addModelFile(` namespace org.acme.sample @@ -45,6 +44,7 @@ describe('Serializer', () => { o String assetId --> SampleParticipant owner o String stringValue + o Double doubleValue } participant SampleParticipant identified by participantId { @@ -53,7 +53,8 @@ describe('Serializer', () => { o String lastName } - transaction SampleTransaction { + transaction SampleTransaction identified by transactionId { + o String transactionId --> SampleAsset asset o String newValue } @@ -61,9 +62,11 @@ describe('Serializer', () => { concept Address { o String city o String country + o Double elevation } - event SampleEvent{ + event SampleEvent identified by eventId { + o String eventId --> SampleAsset asset o String newValue } @@ -113,6 +116,7 @@ describe('Serializer', () => { let resource = factory.newResource('org.acme.sample', 'SampleAsset', '1'); resource.owner = factory.newRelationship('org.acme.sample', 'SampleParticipant', 'alice@email.com'); resource.stringValue = 'the value'; + resource.doubleValue = 3.14; let json = serializer.toJSON(resource, { validate: true }); @@ -120,10 +124,41 @@ describe('Serializer', () => { $class: 'org.acme.sample.SampleAsset', assetId: '1', owner: 'resource:org.acme.sample.SampleParticipant#alice@email.com', - stringValue: 'the value' + stringValue: 'the value', + doubleValue: 3.14 }); }); + it('should throw validation errors during JSON object generation if Double is NaN', () => { + let resource = factory.newResource('org.acme.sample', 'SampleAsset', '1'); + resource.owner = factory.newRelationship('org.acme.sample', 'SampleParticipant', 'alice@email.com'); + resource.stringValue = 'the value'; + resource.doubleValue = NaN; + (() => { + serializer.toJSON(resource); + }).should.throw(/Model violation in instance org.acme.sample.SampleAsset#1 field doubleValue has value NaN/); + }); + + it('should throw validation errors during JSON object generation if Double is Infinity', () => { + let resource = factory.newResource('org.acme.sample', 'SampleAsset', '1'); + resource.owner = factory.newRelationship('org.acme.sample', 'SampleParticipant', 'alice@email.com'); + resource.stringValue = 'the value'; + resource.doubleValue = Infinity; + (() => { + serializer.toJSON(resource); + }).should.throw(/Model violation in instance org.acme.sample.SampleAsset#1 field doubleValue has value Infinity/); + }); + + it('should throw validation errors during JSON object generation if Double is -Infinity', () => { + let resource = factory.newResource('org.acme.sample', 'SampleAsset', '1'); + resource.owner = factory.newRelationship('org.acme.sample', 'SampleParticipant', 'alice@email.com'); + resource.stringValue = 'the value'; + resource.doubleValue = -Infinity; + (() => { + serializer.toJSON(resource); + }).should.throw(/Model violation in instance org.acme.sample.SampleAsset#1 field doubleValue has value -Infinity/); + }); + it('should throw validation errors during JSON object generation if the validate flag is not specified and errors are present', () => { let resource = factory.newResource('org.acme.sample', 'SampleAsset', '1'); (() => { @@ -175,10 +210,12 @@ describe('Serializer', () => { let address = factory.newConcept('org.acme.sample', 'Address'); address.city = 'Winchester'; address.country = 'UK'; + address.elevation = 3.14; const json = serializer.toJSON(address); json.should.deep.equal({ $class: 'org.acme.sample.Address', country: 'UK', + elevation: 3.14, city: 'Winchester' }); }); @@ -187,6 +224,7 @@ describe('Serializer', () => { let resource = factory.newResource('org.acme.sample', 'SampleAsset', '1'); resource.owner = factory.newRelationship('org.acme.sample', 'SampleParticipant', 'alice@email.com'); resource.stringValue = ''; + resource.doubleValue = 3.14; let json = serializer.toJSON(resource, { validate: true }); @@ -194,7 +232,8 @@ describe('Serializer', () => { $class: 'org.acme.sample.SampleAsset', assetId: '1', owner: 'resource:org.acme.sample.SampleParticipant#alice@email.com', - stringValue: '' + stringValue: '', + doubleValue: 3.14 }); }); }); @@ -222,13 +261,15 @@ describe('Serializer', () => { $class: 'org.acme.sample.SampleAsset', assetId: '1', owner: 'resource:org.acme.sample.SampleParticipant#alice@email.com', - stringValue: 'the value' + stringValue: 'the value', + doubleValue: 3.14 }; let resource = serializer.fromJSON(json); resource.should.be.an.instanceOf(Resource); resource.assetId.should.equal('1'); resource.owner.should.be.an.instanceOf(Relationship); resource.stringValue.should.equal('the value'); + resource.doubleValue.should.equal(3.14); }); it('should deserialize a valid transaction', () => { @@ -263,12 +304,14 @@ describe('Serializer', () => { let json = { $class: 'org.acme.sample.Address', city: 'Winchester', - country: 'UK' + country: 'UK', + elevation: 3.14 }; let resource = serializer.fromJSON(json); - resource.should.be.an.instanceOf(Concept); + resource.should.be.an.instanceOf(Resource); resource.city.should.equal('Winchester'); resource.country.should.equal('UK'); + resource.elevation.should.equal(3.14); }); it('should throw validation errors if the validate flag is not specified', () => { diff --git a/packages/concerto-core/test/serializer/complex/complex.js b/packages/concerto-core/test/serializer/complex/complex.js index 416fe4ebe6..433352e7f8 100644 --- a/packages/concerto-core/test/serializer/complex/complex.js +++ b/packages/concerto-core/test/serializer/complex/complex.js @@ -18,7 +18,7 @@ const Factory = require('../../../lib/factory'); const ModelManager = require('../../../lib/modelmanager'); const Serializer = require('../../../lib/serializer'); const fs = require('fs'); -const Util = require('../../composer/systemmodelutility'); +const Util = require('../../composer/composermodelutility'); const Moment = require('moment-mini'); let chai = require('chai'); @@ -34,7 +34,7 @@ describe('Test generating deduplicated JSON for complex models', () => { before(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); const base = fs.readFileSync('./test/serializer/complex/vehicle-lifecycle/base.cto', 'utf8'); const business = fs.readFileSync('./test/serializer/complex/vehicle-lifecycle/business.cto', 'utf8'); diff --git a/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/business.cto b/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/business.cto index d149c78bd4..9123a69439 100644 --- a/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/business.cto +++ b/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/business.cto @@ -19,7 +19,8 @@ import composer.base.Address /** * An abstract participant type in this business network */ -abstract participant Business { +abstract participant Business identified by businessId { + o String businessId o Address headquarters optional o String name optional --> Manager[] managers optional diff --git a/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/manufacturer.cto b/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/manufacturer.cto index ffc07b8d0f..6f29e23b5e 100644 --- a/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/manufacturer.cto +++ b/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/manufacturer.cto @@ -36,7 +36,7 @@ enum OrderStatus { /** * A manufacturer of vehicles */ -participant Manufacturer identified by companyId extends Business { +participant Manufacturer extends Business { o String companyId } diff --git a/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/vda.cto b/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/vda.cto index 7de3125de3..46b7844dec 100644 --- a/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/vda.cto +++ b/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/vda.cto @@ -111,7 +111,8 @@ transaction ApplicationForVehicleRegistrationCertificate { o String previousPostCode optional } -abstract transaction VehicleTransaction { +abstract transaction VehicleTransaction identified by transactionId { + o String transactionId --> Vehicle vehicle } diff --git a/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/vehicle.cto b/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/vehicle.cto index 97c7a8632c..6d737293f1 100644 --- a/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/vehicle.cto +++ b/packages/concerto-core/test/serializer/complex/vehicle-lifecycle/vehicle.cto @@ -21,11 +21,11 @@ import composer.base.Person import composer.business.Business import org.vda.PrivateVehicleTransfer -participant PrivateOwner identified by email extends Person { +participant PrivateOwner extends Person { o String email } -participant Company identified by companyId extends Business { +participant Company extends Business { o String companyId } diff --git a/packages/concerto-core/test/serializer/instancegenerator.js b/packages/concerto-core/test/serializer/instancegenerator.js index 36a824549d..0375eab22c 100644 --- a/packages/concerto-core/test/serializer/instancegenerator.js +++ b/packages/concerto-core/test/serializer/instancegenerator.js @@ -19,7 +19,7 @@ const InstanceGenerator = require('../../lib/serializer/instancegenerator'); const ModelManager = require('../../lib/modelmanager'); const TypedStack = require('../../lib/serializer/typedstack'); const ValueGenerator = require('../../lib/serializer/valuegenerator'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); const chai = require('chai'); @@ -41,7 +41,7 @@ describe('InstanceGenerator', () => { beforeEach(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); factory = new Factory(modelManager); parameters = { modelManager: modelManager, @@ -76,6 +76,16 @@ describe('InstanceGenerator', () => { }`); resource.theValue.should.be.a('string'); }); + + it('should generate a default value for a string property with a regex', () => { + let resource = test(`namespace org.acme.test + asset MyAsset identified by assetId { + o String assetId + o String theValue regex = /foo/ + }`); + resource.theValue.should.be.a('string'); + }); + it('should not throw a recursion error', () => { let resource = test(`namespace org.acme.test participant MyParticipant identified by participantId{ @@ -171,6 +181,15 @@ describe('InstanceGenerator', () => { resource.theValue.should.be.a('number'); }); + it('should generate a default value for an integer property with a range', () => { + let resource = test(`namespace org.acme.test + asset MyAsset identified by assetId { + o String assetId + o Integer theValue range = [-1,1] + }`); + resource.theValue.should.be.a('number'); + }); + it('should generate a default value for an integer array property', () => { let resource = test(`namespace org.acme.test asset MyAsset identified by assetId { @@ -190,6 +209,15 @@ describe('InstanceGenerator', () => { resource.theValue.should.be.a('number'); }); + it('should generate a default value for a long property with a range', () => { + let resource = test(`namespace org.acme.test + asset MyAsset identified by assetId { + o String assetId + o Long theValue range = [-1,1] + }`); + resource.theValue.should.be.a('number'); + }); + it('should generate a default value for a long array property', () => { let resource = test(`namespace org.acme.test asset MyAsset identified by assetId { @@ -209,6 +237,15 @@ describe('InstanceGenerator', () => { resource.theValue.should.be.a('number'); }); + it('should generate a default value for a double property with a range', () => { + let resource = test(`namespace org.acme.test + asset MyAsset identified by assetId { + o String assetId + o Double theValue range = [-3.142, 3.143] + }`); + resource.theValue.should.be.a('number'); + }); + it('should generate a default value for a double array property', () => { let resource = test(`namespace org.acme.test asset MyAsset identified by assetId { @@ -378,11 +415,14 @@ describe('InstanceGenerator', () => { it('should generate concrete subclass for abstract reference', function () { let resource = test(`namespace org.acme.test + event MyEvent identified by eventId { + o String eventId + } asset MyAsset identified by id { o String id - --> Asset theValue + --> MyEvent theValue }`); - resource.theValue.getType().should.equal('MyAsset'); + resource.theValue.getType().should.equal('MyEvent'); }); }); diff --git a/packages/concerto-core/test/serializer/jsongenerator.js b/packages/concerto-core/test/serializer/jsongenerator.js index 84b8e569de..5e13726e23 100644 --- a/packages/concerto-core/test/serializer/jsongenerator.js +++ b/packages/concerto-core/test/serializer/jsongenerator.js @@ -19,7 +19,7 @@ const JSONGenerator = require('../../lib/serializer/jsongenerator'); const ModelManager = require('../../lib/modelmanager'); const TypedStack = require('../../lib/serializer/typedstack'); const ModelUtil = require('../../lib/modelutil'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); let chai = require('chai'), should = chai.should(); @@ -40,7 +40,7 @@ describe('JSONGenerator', () => { before(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addModelFile(` namespace org.acme asset MyAsset1 identified by assetId { @@ -132,16 +132,16 @@ describe('JSONGenerator', () => { it('should pass through an integer object', () => { jsonGenerator.convertToJSON({ getType: () => { return 'Integer'; } }, 123456).should.equal(123456); - ergoJsonGenerator.convertToJSON({ getType: () => { return 'Integer'; } }, 123456).nat.should.equal(123456); + ergoJsonGenerator.convertToJSON({ getType: () => { return 'Integer'; } }, 123456).$nat.should.equal(123456); }); - it('should pass through a double object', () => { + it('should pass through a finite double object', () => { jsonGenerator.convertToJSON({ getType: () => { return 'Double'; } }, 3.142).should.equal(3.142); }); it('should pass through a long object', () => { jsonGenerator.convertToJSON({ getType: () => { return 'Long'; } }, 1234567890).should.equal(1234567890); - ergoJsonGenerator.convertToJSON({ getType: () => { return 'Long'; } }, 1234567890).nat.should.equal(1234567890); + ergoJsonGenerator.convertToJSON({ getType: () => { return 'Long'; } }, 1234567890).$nat.should.equal(1234567890); }); it('should pass through a string object', () => { @@ -289,7 +289,7 @@ describe('JSONGenerator', () => { options.stack.push('string'); (() => { jsonGenerator.visitClassDeclaration(relationshipDeclaration4, options); - }).should.throw(/Expected a Resource or a Concept/); + }).should.throw(/Expected a Resource, but found string/); }); it('should generate a relationship (Ergo)', () => { @@ -354,6 +354,7 @@ describe('JSONGenerator', () => { it('should populate if a primitive string', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return true;}, 'getType':function(){return 'String';} }; @@ -368,9 +369,82 @@ describe('JSONGenerator', () => { should.equal(jsonGenerator.visitField(field, parameters), 'WONGA-1'); }); + it('should populate if an optional primitive string', () => { + let field = { + 'isArray':function(){return false;}, + 'isOptional':function(){return true;}, + 'isPrimitive':function(){return true;}, + 'getType':function(){return 'String';} + }; + isEnumStub.returns(false); + let primitive = 'WONGA-1'; + let parameters = { + stack: new TypedStack({}), + modelManager: modelManager, + seenResources: new Set() + }; + parameters.stack.push(primitive); + should.equal(jsonGenerator.visitField(field, parameters), 'WONGA-1'); + }); + + it('should populate if an optional primitive string (null)', () => { + let field = { + 'isArray':function(){return false;}, + 'isOptional':function(){return true;}, + 'isPrimitive':function(){return true;}, + 'getType':function(){return 'String';} + }; + isEnumStub.returns(false); + let primitive = null; + let parameters = { + stack: new TypedStack({}), + modelManager: modelManager, + seenResources: new Set() + }; + parameters.stack.push(primitive); + should.equal(jsonGenerator.visitField(field, parameters), null); + }); + + it('should populate if an optional primitive string (Ergo)', () => { + let field = { + 'isArray':function(){return false;}, + 'isOptional':function(){return true;}, + 'isPrimitive':function(){return true;}, + 'getType':function(){return 'String';} + }; + isEnumStub.returns(false); + let primitive = 'WONGA-1'; + let parameters = { + stack: new TypedStack({}), + modelManager: modelManager, + seenResources: new Set() + }; + parameters.stack.push(primitive); + should.equal(ergoJsonGenerator.visitField(field, parameters).$left, 'WONGA-1'); + }); + + it('should populate if an optional primitive string (null) (Ergo)', () => { + let field = { + 'isArray':function(){return false;}, + 'isOptional':function(){return true;}, + 'isPrimitive':function(){return true;}, + 'getType':function(){return 'String';} + }; + isEnumStub.returns(false); + let primitive = null; + let parameters = { + stack: new TypedStack({}), + modelManager: modelManager, + seenResources: new Set() + }; + parameters.stack.push(primitive); + should.equal(ergoJsonGenerator.visitField(field, parameters).$right, null); + }); + it('should populate if a primitive integer', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return true;}, 'getType':function(){return 'Integer';} }; @@ -388,6 +462,7 @@ describe('JSONGenerator', () => { it('should populate if a primitive integer (Ergo)', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return true;}, 'getType':function(){return 'Integer';} }; @@ -399,12 +474,13 @@ describe('JSONGenerator', () => { seenResources: new Set() }; parameters.stack.push(primitive); - should.equal(ergoJsonGenerator.visitField(field, parameters).nat, 2); + should.equal(ergoJsonGenerator.visitField(field, parameters).$nat, 2); }); it('should populate if a primitive double', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return true;}, 'getType':function(){return 'Double';} }; @@ -422,6 +498,7 @@ describe('JSONGenerator', () => { it('should populate if a primitive Long', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return true;}, 'getType':function(){return 'Long';} }; @@ -439,6 +516,7 @@ describe('JSONGenerator', () => { it('should populate if a primitive Long', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return true;}, 'getType':function(){return 'Long';} }; @@ -450,12 +528,13 @@ describe('JSONGenerator', () => { seenResources: new Set() }; parameters.stack.push(primitive); - should.equal(ergoJsonGenerator.visitField(field, parameters).nat, 1234567890); + should.equal(ergoJsonGenerator.visitField(field, parameters).$nat, 1234567890); }); it('should populate if a primitive Boolean', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return true;}, 'getType':function(){return 'Boolean';} }; @@ -473,6 +552,7 @@ describe('JSONGenerator', () => { it('should populate if an Enum', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return false;}, 'getType':function(){return 'String';} }; @@ -491,6 +571,7 @@ describe('JSONGenerator', () => { it('should populate if an Enum (Ergo)', () => { let field = { 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return false;}, 'getType':function(){return 'String';}, 'getParent':function(){ @@ -522,19 +603,20 @@ describe('JSONGenerator', () => { }; parameters.stack.push(primitive); let result = ergoJsonGenerator.visitField(field, parameters); - result.should.have.property('type'); - result.should.have.property('data'); - result.type[0].should.equal('MyEnum'); - result.data.should.have.property('right'); - result.data.right.should.have.property('right'); - result.data.right.right.should.have.property('left'); - result.data.right.right.left.should.equal('WONGA-1'); + result.should.have.property('$class'); + result.should.have.property('$data'); + result.$class[0].should.equal('MyEnum'); + result.$data.should.have.property('$right'); + result.$data.$right.should.have.property('$right'); + result.$data.$right.$right.should.have.property('$left'); + result.$data.$right.$right.$left.should.equal('WONGA-1'); }); it('should recurse if an object', () => { let field = { 'getName':function(){return 'vehicle';}, 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return false;}, 'getParent':function(){return 'vehicle';}, 'getType':function(){return 'String';} @@ -567,6 +649,7 @@ describe('JSONGenerator', () => { let field = { 'getName':function(){return 'vehicle';}, 'isArray':function(){return false;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return false;}, 'getParent':function(){return 'vehicle';}, 'getType':function(){return 'String';} @@ -590,7 +673,7 @@ describe('JSONGenerator', () => { let result = ergoJsonGenerator.visitField(field,parameters); result.should.deep.equal({ '$class': 'org.acme.sample.Car', color: 'GREEN', - numberOfSeats: { 'nat' : '2' }, + numberOfSeats: { '$nat' : '2' }, numberPlate: 'PENGU1N' }); spy.callCount.should.equal(4); // We call it once at the start, then it recurses three times }); @@ -598,6 +681,7 @@ describe('JSONGenerator', () => { it('should populate an array if array contains primitives', () => { let field = { 'isArray':function(){return true;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return true;}, 'getType':function(){return 'String';} }; @@ -618,6 +702,7 @@ describe('JSONGenerator', () => { let field = { 'getName':function(){return 'vehicle';}, 'isArray':function(){return true;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return false;}, 'getParent':function(){return 'vehicle';}, 'getType':function(){return 'Integer';} @@ -643,6 +728,7 @@ describe('JSONGenerator', () => { let field = { 'getName':function(){return 'vehicle';}, 'isArray':function(){return true;}, + 'isOptional':function(){return false;}, 'isPrimitive':function(){return false;}, 'getParent':function(){return 'vehicle';}, 'getType':function(){return 'String';} diff --git a/packages/concerto-core/test/serializer/jsonpopulator.js b/packages/concerto-core/test/serializer/jsonpopulator.js index 2bf035bb57..e0ac890c9c 100644 --- a/packages/concerto-core/test/serializer/jsonpopulator.js +++ b/packages/concerto-core/test/serializer/jsonpopulator.js @@ -21,8 +21,9 @@ const ModelManager = require('../../lib/modelmanager'); const Relationship = require('../../lib/model/relationship'); const Resource = require('../../lib/model/resource'); const TypedStack = require('../../lib/serializer/typedstack'); +const ValidationException = require('../../lib/serializer/validationexception'); const TypeNotFoundException = require('../../lib/typenotfoundexception'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); require('chai').should(); @@ -41,11 +42,12 @@ describe('JSONPopulator', () => { before(() => { modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); modelManager.addModelFile(` namespace org.acme asset MyAsset1 identified by assetId { o String assetId + o Integer assetValue optional } asset MyAsset2 identified by assetId { o String assetId @@ -114,13 +116,60 @@ describe('JSONPopulator', () => { value.format('YYYY-MM-DDTHH:mm:ss.SSS[Z]').should.equal(Moment.parseZone('2016-10-20T05:34:03.000Z').format('YYYY-MM-DDTHH:mm:ss.SSS[Z]')); }); - it('should convert to integers from strings', () => { + it('should not convert to dates from invalid moments', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('DateTime'); + (() => { + jsonPopulator.convertToObject(field, 'foo'); + }).should.throw(ValidationException, /Expected value "foo" to be of type DateTime/); + }); + + it('should not convert to dates from null', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('DateTime'); + (() => { + jsonPopulator.convertToObject(field, null); + }).should.throw(ValidationException, /Expected value null to be of type DateTime/); + }); + + it('should not convert to dates from undefined', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('DateTime'); + (() => { + jsonPopulator.convertToObject(field, undefined); + }).should.throw(ValidationException, /Expected value undefined to be of type DateTime/); + }); + + it('should not convert to dates when not in ISO 8601 format', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('DateTime'); + (() => { + jsonPopulator.convertToObject(field, 'December 17, 1995 03:24:00'); + }).should.throw(ValidationException, /Expected value "December 17, 1995 03:24:00" to be of type DateTime/); + }); + + it('should not convert to integers from strings', () => { let field = sinon.createStubInstance(Field); field.getType.returns('Integer'); - let value = jsonPopulator.convertToObject(field, '32768'); - value.should.equal(32768); - value = ergoJsonPopulator.convertToObject(field, {'nat':'32768'}); - value.should.equal(32768); + (() => { + jsonPopulator.convertToObject(field, '32768'); + }).should.throw(ValidationException, /Expected value "32768" to be of type Integer/); + }); + + it('should not convert to integer from null', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Integer'); + (() => { + jsonPopulator.convertToObject(field, null); + }).should.throw(ValidationException, /Expected value null to be of type Integer/); + }); + + it('should not convert to integer from undefined', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Integer'); + (() => { + jsonPopulator.convertToObject(field, undefined); + }).should.throw(ValidationException, /Expected value undefined to be of type Integer/); }); it('should convert to integers from numbers', () => { @@ -128,17 +177,32 @@ describe('JSONPopulator', () => { field.getType.returns('Integer'); let value = jsonPopulator.convertToObject(field, 32768); value.should.equal(32768); - value = ergoJsonPopulator.convertToObject(field, {'nat':'32768'}); + value = ergoJsonPopulator.convertToObject(field, {'$nat':32768}); value.should.equal(32768); }); - it('should convert to longs from strings', () => { + it('should not convert to longs from strings', () => { let field = sinon.createStubInstance(Field); field.getType.returns('Long'); - let value = jsonPopulator.convertToObject(field, '32768'); - value.should.equal(32768); - value = ergoJsonPopulator.convertToObject(field, {'nat':'32768'}); - value.should.equal(32768); + (() => { + jsonPopulator.convertToObject(field, '32768'); + }).should.throw(ValidationException, /Expected value "32768" to be of type Long/); + }); + + it('should not convert to long from null', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Long'); + (() => { + jsonPopulator.convertToObject(field, null); + }).should.throw(ValidationException, /Expected value null to be of type Long/); + }); + + it('should not convert to long from undefined', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Long'); + (() => { + jsonPopulator.convertToObject(field, undefined); + }).should.throw(ValidationException, /Expected value undefined to be of type Long/); }); it('should convert to longs from numbers', () => { @@ -146,15 +210,40 @@ describe('JSONPopulator', () => { field.getType.returns('Long'); let value = jsonPopulator.convertToObject(field, 32768); value.should.equal(32768); - value = ergoJsonPopulator.convertToObject(field, {'nat':'32768'}); + value = ergoJsonPopulator.convertToObject(field, {'$nat':32768}); value.should.equal(32768); }); - it('should convert to doubles from strings', () => { + it('should not convert to longs from numbers that are not integers', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Long'); + (() => { + jsonPopulator.convertToObject(field, 32.768); + }).should.throw(ValidationException, /Expected value 32.768 to be of type Long/); + }); + + it('should not convert to doubles from strings', () => { let field = sinon.createStubInstance(Field); field.getType.returns('Double'); - let value = jsonPopulator.convertToObject(field, '32.768'); - value.should.equal(32.768); + (() => { + jsonPopulator.convertToObject(field, '32.768'); + }).should.throw(ValidationException, /Expected value "32.768" to be of type Double/); + }); + + it('should not convert to double from null', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Double'); + (() => { + jsonPopulator.convertToObject(field, null); + }).should.throw(ValidationException, /Expected value null to be of type Double/); + }); + + it('should not convert to double from undefined', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Double'); + (() => { + jsonPopulator.convertToObject(field, undefined); + }).should.throw(ValidationException, /Expected value undefined to be of type Double/); }); it('should convert to doubles from numbers', () => { @@ -164,18 +253,43 @@ describe('JSONPopulator', () => { value.should.equal(32.768); }); - it('should convert to booleans from strings', () => { + it('should convert to booleans from true', () => { let field = sinon.createStubInstance(Field); field.getType.returns('Boolean'); - let value = jsonPopulator.convertToObject(field, 'true'); + let value = jsonPopulator.convertToObject(field, true); value.should.equal(true); }); - it('should convert to booleans from numbers', () => { + it('should not convert to booleans from strings', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Boolean'); + (() => { + jsonPopulator.convertToObject(field, 'true'); + }).should.throw(ValidationException, /Expected value "true" to be of type Boolean/); + }); + + it('should not convert to booleans from numbers', () => { let field = sinon.createStubInstance(Field); field.getType.returns('Boolean'); - let value = jsonPopulator.convertToObject(field, false); - value.should.equal(false); + (() => { + jsonPopulator.convertToObject(field, 32.768); + }).should.throw(ValidationException, /Expected value 32.768 to be of type Boolean/); + }); + + it('should not convert to boolean from null', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Boolean'); + (() => { + jsonPopulator.convertToObject(field, null); + }).should.throw(ValidationException, /Expected value null to be of type Boolean/); + }); + + it('should not convert to boolean from undefined', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('Boolean'); + (() => { + jsonPopulator.convertToObject(field, undefined); + }).should.throw(ValidationException, /Expected value undefined to be of type Boolean/); }); it('should convert to strings from strings', () => { @@ -185,11 +299,28 @@ describe('JSONPopulator', () => { value.should.equal('hello world'); }); - it('should convert to strings from numbers', () => { + it('should not convert to strings from numbers', () => { let field = sinon.createStubInstance(Field); field.getType.returns('String'); - let value = jsonPopulator.convertToObject(field, 32768); - value.should.equal('32768'); + (() => { + jsonPopulator.convertToObject(field, 32.768); + }).should.throw(ValidationException, /Expected value 32.768 to be of type String/); + }); + + it('should not convert to string from null', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('String'); + (() => { + jsonPopulator.convertToObject(field, null); + }).should.throw(ValidationException, /Expected value null to be of type String/); + }); + + it('should not convert to string from undefined', () => { + let field = sinon.createStubInstance(Field); + field.getType.returns('String'); + (() => { + jsonPopulator.convertToObject(field, undefined); + }).should.throw(ValidationException, /Expected value undefined to be of type String/); }); }); @@ -230,6 +361,78 @@ describe('JSONPopulator', () => { sinon.assert.calledWith(mockFactory.newResource, 'org.acme', 'MyAsset1', 'asset1'); }); + it('should create a new resource from an object using a $class value that matches the model with optional integer', () => { + let options = { + jsonStack: new TypedStack({}), + resourceStack: new TypedStack({}), + factory: mockFactory, + modelManager: modelManager + }; + let mockResource = sinon.createStubInstance(Resource); + mockFactory.newResource.withArgs('org.acme', 'MyAsset1', 'asset1').returns(mockResource); + let resource = jsonPopulator.convertItem(assetDeclaration1, { + $class: 'org.acme.MyAsset1', + assetId: 'asset1', + assetValue: 1 + }, options); + resource.should.be.an.instanceOf(Resource); + sinon.assert.calledWith(mockFactory.newResource, 'org.acme', 'MyAsset1', 'asset1'); + }); + + it('should create a new resource from an object using a $class value that matches the model with optional intege (Ergo)', () => { + let options = { + jsonStack: new TypedStack({}), + resourceStack: new TypedStack({}), + factory: mockFactory, + modelManager: modelManager + }; + let mockResource = sinon.createStubInstance(Resource); + mockFactory.newResource.withArgs('org.acme', 'MyAsset1', 'asset1').returns(mockResource); + let resource = ergoJsonPopulator.convertItem(assetDeclaration1, { + $class: 'org.acme.MyAsset1', + assetId: 'asset1', + assetValue: { '$left' : { '$nat' : 1 } } + }, options); + resource.should.be.an.instanceOf(Resource); + sinon.assert.calledWith(mockFactory.newResource, 'org.acme', 'MyAsset1', 'asset1'); + }); + + it('should create a new resource from an object using a $class value that matches the model with optional integer (null)', () => { + let options = { + jsonStack: new TypedStack({}), + resourceStack: new TypedStack({}), + factory: mockFactory, + modelManager: modelManager + }; + let mockResource = sinon.createStubInstance(Resource); + mockFactory.newResource.withArgs('org.acme', 'MyAsset1', 'asset1').returns(mockResource); + let resource = jsonPopulator.convertItem(assetDeclaration1, { + $class: 'org.acme.MyAsset1', + assetId: 'asset1', + assetValue: null + }, options); + resource.should.be.an.instanceOf(Resource); + sinon.assert.calledWith(mockFactory.newResource, 'org.acme', 'MyAsset1', 'asset1'); + }); + + it('should create a new resource from an object using a $class value that matches the model with optional integer (null) (Ergo)', () => { + let options = { + jsonStack: new TypedStack({}), + resourceStack: new TypedStack({}), + factory: mockFactory, + modelManager: modelManager + }; + let mockResource = sinon.createStubInstance(Resource); + mockFactory.newResource.withArgs('org.acme', 'MyAsset1', 'asset1').returns(mockResource); + let resource = ergoJsonPopulator.convertItem(assetDeclaration1, { + $class: 'org.acme.MyAsset1', + assetId: 'asset1', + assetValue: { '$right' : null } + }, options); + resource.should.be.an.instanceOf(Resource); + sinon.assert.calledWith(mockFactory.newResource, 'org.acme', 'MyAsset1', 'asset1'); + }); + it('should create a new resource from an object using a $class value even if it does not match the model', () => { let options = { jsonStack: new TypedStack({}), diff --git a/packages/concerto-core/test/serializer/objectvalidator.js b/packages/concerto-core/test/serializer/objectvalidator.js new file mode 100644 index 0000000000..f29f970b4d --- /dev/null +++ b/packages/concerto-core/test/serializer/objectvalidator.js @@ -0,0 +1,312 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const ModelManager = require('../../lib/modelmanager'); +const ObjectValidator = require('../../lib/serializer/objectvalidator'); +const TypedStack = require('../../lib/serializer/typedstack'); +const Concerto = require('../../lib/concerto'); +const chai = require('chai'); +chai.should(); +chai.use(require('chai-things')); + +describe('ObjectValidator', function () { + + let modelManager; + let concerto; + let objectValidator; + + before(function () { + modelManager = new ModelManager(); + modelManager.addModelFile(`namespace test + + concept Wheel { + o String brand + } + + participant Person identified by email { + o String email + } + + concept Manager identified { + o String name + } + + enum TestEnum { + o ONE + o TWO + o THREE + } + + concept Vehicle { + o String color optional + o Wheel[] wheels optional + o String stringProperty optional + o Integer integerProperty optional + o Boolean booleanProperty optional + o DateTime dateTimeProperty optional + o String validatedStringProperty regex=/good/ optional + o Person owner optional + --> Person[] previousOwners optional + o TestEnum[] testEnums optional + --> Person lastOwner optional + } + `, 'test.cto'); + }); + + beforeEach(function () { + concerto = new Concerto(modelManager); + objectValidator = new ObjectValidator(concerto); + }); + + afterEach(function () { + }); + + describe('#constructor', () => { + it('should fail if concerto not supplied', () => { + (function () { + new ObjectValidator(null); + }).should.throw(/Missing concerto instance/); + }); + }); + describe('#checkEnum', () => { + it('should fail if instance is not an array', () => { + const data = { + $class : 'test.Vehicle', + testEnums : 'ONE' + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/expected type TestEnum\[\]/); + }); + + it('should pass', () => { + const data = { + $class : 'test.Vehicle', + color: 'red', + wheels : [{ + $class : 'test.Wheel', + brand : 'Michelin' + }] + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }); + }); + + describe('#checkItem', () => { + it('should fail if property not a number', () => { + const data = { + $class : 'test.Vehicle', + integerProperty: 'bad', + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/expected type Integer/); + }); + + it('should fail if property not a string', () => { + const data = { + $class : 'test.Vehicle', + stringProperty: 1, + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/expected type String/); + }); + + it('should fail if property type is symbol', () => { + const data = { + $class : 'test.Vehicle', + stringProperty: Symbol('foo'), + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/expected type String/); + }); + + it('should fail if property not a boolean', () => { + const data = { + $class : 'test.Vehicle', + booleanProperty: 'false', + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/expected type Boolean/); + }); + + it('should fail if property not a DataTime', () => { + const data = { + $class : 'test.Vehicle', + dateTimeProperty: true, + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/expected type DateTime/); + }); + + it('should fail if property fails field validator', () => { + const data = { + $class : 'test.Vehicle', + validatedStringProperty: 'bad', + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/failed to match validation regex: \/good\//); + }); + + it('should fail if complex property is not compatible', () => { + const data = { + $class : 'test.Vehicle', + owner: { + $class: 'test.Wheel', + brand: 'Michelin' + }, + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/test.Wheel that is not derived from test.Person/); + }); + + it('should fail complex property that references a missing type', () => { + const data = { + $class : 'test.Vehicle', + owner: { + $class: 'test.Missing', + brand: 'Michelin' + }, + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/Type Missing is not defined in namespace test/); + }); + }); + + describe('#visitRelationshipDeclaration', () => { + it('should fail if property not an array of relationships', () => { + const data = { + $class : 'test.Vehicle', + previousOwners: 'bad', + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/Instance undefined has property previousOwners with type undefined that is not derived from test.Person\[\]/); + }); + }); + + describe('#visitRelationship', () => { + it('should pass with instance if convertResourcesToRelationships is set', () => { + const data = { + $class : 'test.Vehicle', + lastOwner: { + $class : 'test.Person', + email : 'test@example.com' + }, + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + objectValidator = new ObjectValidator(concerto, {permitResourcesForRelationships : true}); + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }); + + it('should fail with instance if convertResourcesToRelationships is not set', () => { + const data = { + $class : 'test.Vehicle', + lastOwner: { + $class : 'test.Person', + email : 'test@example.com' + }, + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/expected a Relationship/); + }); + + it('should fail with non-identifiable instance if convertResourcesToRelationships is not set', () => { + const data = { + $class : 'test.Vehicle', + lastOwner: { + $class : 'test.Wheel', + brand : 'test@example.com' + }, + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/expected a Relationship/); + }); + + it('should fail with a relationship to a non identifiable type', () => { + const data = { + $class : 'test.Vehicle', + lastOwner: 'resource:test.Wheel#Michelin', + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/Relationship can only be to identified types/); + }); + + it('should fail with a non assignable relationship', () => { + const data = { + $class : 'test.Vehicle', + lastOwner: 'resource:test.Manager#Dan', + }; + const parameters = {}; + parameters.stack = new TypedStack(data); + (function () { + objectValidator.visit(concerto.getTypeDeclaration(data), parameters); + }).should.throw(/not derived from test.Person/); + }); + + + }); + +}); diff --git a/packages/concerto-core/test/serializer/resourcevalidator.js b/packages/concerto-core/test/serializer/resourcevalidator.js index 1a5464fc75..5f1a0232f7 100644 --- a/packages/concerto-core/test/serializer/resourcevalidator.js +++ b/packages/concerto-core/test/serializer/resourcevalidator.js @@ -24,7 +24,7 @@ const Field = require('../../lib/introspect/field'); const Resource = require('../../lib/model/resource'); const ModelUtil = require('../../lib/modelutil'); const ClassDeclaration = require('../../lib/introspect/classdeclaration'); -const Util = require('../composer/systemmodelutility'); +const Util = require('../composer/composermodelutility'); const Moment = require('moment-mini'); const sinon = require('sinon'); @@ -61,8 +61,7 @@ describe('ResourceValidator', function () { participant Person identified by ssn { o String ssn } - participant Employee identified by employeeId extends Person { - o String employeeId + participant Employee extends Person { } concept Data { o String name @@ -74,8 +73,9 @@ describe('ResourceValidator', function () { import org.acme.l1.Person asset Vehicle extends Base { o Integer numberOfWheels + o Double milage } - participant PrivateOwner identified by employeeId extends Person { + participant PrivateOwner extends Person { o String employeeId } `; @@ -107,7 +107,7 @@ describe('ResourceValidator', function () { sandbox = sinon.createSandbox(); resourceValidator = new ResourceValidator(); modelManager = new ModelManager(); - Util.addComposerSystemModels(modelManager); + Util.addComposerModel(modelManager); factory = new Factory(modelManager); }); @@ -169,17 +169,11 @@ describe('ResourceValidator', function () { field.accept(resourceValidator,parameters ); }); - it('should detect a relationship to a concept', function () { + it('should reject a relationship to a concept', function () { const car = factory.newResource('org.acme.l3', 'Car', '123'); - car.owner = factory.newRelationship('org.acme.l3', 'TestConcept'); - car.model = 'FOO'; - - const typedStack = new TypedStack( car ); - const vehicleDeclaration = modelManager.getType('org.acme.l3.Car'); - const parameters = { stack : typedStack, 'modelManager' : modelManager, rootResourceIdentifier : 'TEST' }; (function () { - vehicleDeclaration.accept(resourceValidator,parameters ); - }).should.throw(/Cannot have a relationship to a concept. Relationships must be to resources./); + car.owner = factory.newRelationship('org.acme.l3', 'TestConcept'); + }).should.throw(/Cannot create a relationship to org.acme.l3.TestConcept, it is not identifiable./); }); it('should detect a relationship to a non array', function () { @@ -414,6 +408,7 @@ describe('ResourceValidator', function () { vehicle.$identifier = ''; // empty the identifier vehicle.model = 'Ford'; vehicle.numberOfWheels = 4; + vehicle.milage = 3.14; const typedStack = new TypedStack(vehicle); const assetDeclaration = modelManager.getType('org.acme.l3.Car'); const parameters = { stack : typedStack, 'modelManager' : modelManager, rootResourceIdentifier : 'ABC' }; @@ -423,6 +418,21 @@ describe('ResourceValidator', function () { }).should.throw(/has an empty identifier/); }); + it('should reject a Double which is not finite', function () { + const vehicle = factory.newResource('org.acme.l3', 'Car', 'foo'); + vehicle.$identifier = '42'; + vehicle.model = 'Ford'; + vehicle.numberOfWheels = 4; + vehicle.milage = NaN; // NaN + const typedStack = new TypedStack(vehicle); + const assetDeclaration = modelManager.getType('org.acme.l3.Car'); + const parameters = { stack : typedStack, 'modelManager' : modelManager, rootResourceIdentifier : 'ABC' }; + + (() => { + assetDeclaration.accept(resourceValidator,parameters); + }).should.throw(/Model violation in instance org.acme.l3.Car#42 field milage has value NaN/); + }); + it('should report undeclared field if not identifiable', () => { const data = factory.newConcept('org.acme.l1', 'Data'); data.name = 'name'; @@ -500,6 +510,7 @@ describe('ResourceValidator', function () { mockResource = sinon.createStubInstance(Resource); mockClassDeclaration = sinon.createStubInstance(ClassDeclaration); mockClassDeclaration.isConcept.returns(false); + mockClassDeclaration.getIdentifierFieldName.returns('$identifier'); parameters = {rootResourceIdentifier: 'identifier', modelManager: {getType: () => {return mockClassDeclaration;}}}; sandbox.stub(ModelUtil, 'isAssignableTo').returns(true); }); diff --git a/packages/concerto-core/test/serializer/typedstack.js b/packages/concerto-core/test/serializer/typedstack.js index 883dae2525..283cce4143 100644 --- a/packages/concerto-core/test/serializer/typedstack.js +++ b/packages/concerto-core/test/serializer/typedstack.js @@ -27,10 +27,6 @@ describe('TypedStack', function () { assert.throws( function() {ts.push(1, String);}, /.+Did not find expected type Function as argument to push. Found: 1/, 'did not throw with expected message'); }); - it('check push with null', function() { - const ts = new TypedStack('ROOT'); - assert.throws( function() {ts.push(null);}, /.+Pushing null data!/, 'did not throw with expected message'); - }); }); describe('#pop', function() { @@ -47,13 +43,9 @@ describe('TypedStack', function () { }); describe('#peek', () => { - it('should throw an error if value given is null', () => { + it('should throw an error if value given has wrong types', () => { const ts = new TypedStack('ROOT'); - (() => { - // Set the top of the stack to null - ts.stack = [null]; - ts.peek(null); - }).should.throw(/Pop returned invalid data/); + assert.throws( function() {ts.peek(Number);}, /.+Found: ROOT/, 'did not throw with expected message'); }); }); }); diff --git a/packages/concerto-core/test/serializer/valuegenerator.js b/packages/concerto-core/test/serializer/valuegenerator.js index 0f2e54135c..6169165c6d 100644 --- a/packages/concerto-core/test/serializer/valuegenerator.js +++ b/packages/concerto-core/test/serializer/valuegenerator.js @@ -65,6 +65,14 @@ describe('ValueGenerator', function() { it('getString should return a string', function() { assertFunctionReturnsType('getString', 'string'); }); + + it('getRange should return a number', function() { + assertFunctionReturnsType('getRange', 'number'); + }); + + it('getRegex should return a string', function() { + assertFunctionReturnsType('getRegex', 'string'); + }); }); describe('EmptyValueGenerator', function() { @@ -78,6 +86,63 @@ describe('ValueGenerator', function() { const output = ValueGeneratorFactory.empty().getArray(() => ''); expect(output).to.be.a('Array').that.is.empty; }); + + it('getRegex should return a string that matches the regex', function() { + const regex = /\S+\.(zip|docx)$/; + const output = ValueGeneratorFactory.empty().getRegex(regex); + expect(regex.test(output)).to.be.true; + }); + + it('getRange should return a Long in range', function() { + const output = ValueGeneratorFactory.empty().getRange(0, 100, 'Long'); + expect(output).to.be.a('number'); + expect(output).to.be.at.least(0); + expect(output).to.be.at.most(100); + + const output2 = ValueGeneratorFactory.empty().getRange(null, 100, 'Long'); + expect(output2).to.be.a('number'); + expect(output2).to.be.at.least(-Math.pow(2, 32)); + expect(output2).to.be.at.most(100); + + const output3 = ValueGeneratorFactory.empty().getRange(0, null, 'Long'); + expect(output3).to.be.a('number'); + expect(output3).to.be.at.least(0); + expect(output3).to.be.at.most(Math.pow(2, 32)); + }); + + it('getRange should return an Integer in range', function() { + const output = ValueGeneratorFactory.empty().getRange(0, 100, 'Integer'); + expect(output).to.be.a('number'); + expect(output).to.be.at.least(0); + expect(output).to.be.at.most(100); + + const output2 = ValueGeneratorFactory.empty().getRange(null, 100, 'Integer'); + expect(output2).to.be.a('number'); + expect(output2).to.be.at.least(-Math.pow(2, 16)); + expect(output2).to.be.at.most(100); + + const output3 = ValueGeneratorFactory.empty().getRange(0, null, 'Integer'); + expect(output3).to.be.a('number'); + expect(output3).to.be.at.least(0); + expect(output3).to.be.at.most(Math.pow(2, 16)); + }); + + it('getRange should return a Double in range', function() { + const output = ValueGeneratorFactory.empty().getRange(0.0, 100.0, 'Double'); + expect(output).to.be.a('number'); + expect(output).to.be.at.least(0.0); + expect(output).to.be.at.most(100.0); + + const output2 = ValueGeneratorFactory.empty().getRange(null, 100, 'Double'); + expect(output2).to.be.a('number'); + expect(output2).to.be.at.least(-Math.pow(2, 32)); + expect(output2).to.be.at.most(100.0); + + const output3 = ValueGeneratorFactory.empty().getRange(0, null, 'Double'); + expect(output3).to.be.a('number'); + expect(output3).to.be.at.least(0.0); + expect(output3).to.be.at.most(Math.pow(2, 32)); + }); }); describe('SampleValueGenerator', function() { @@ -92,6 +157,81 @@ describe('ValueGenerator', function() { const output = ValueGeneratorFactory.sample().getArray(() => value); expect(output).to.be.a('Array').and.deep.equal([value]); }); + + it('getRegex should return a string that matches the regex', function() { + const regex = /\S+\.(zip|docx)$/; + const output = ValueGeneratorFactory.sample().getRegex(regex); + expect(regex.test(output)).to.be.true; + }); + + it('getRange should return a Long in range', function() { + const output = ValueGeneratorFactory.sample().getRange(0, 100, 'Long'); + expect(output).to.be.a('number'); + expect(output).to.be.at.least(0); + expect(output).to.be.at.most(100); + + const output2 = ValueGeneratorFactory.sample().getRange(null, 100, 'Long'); + expect(output2).to.be.a('number'); + expect(output2).to.be.at.least(-Math.pow(2, 32)); + expect(output2).to.be.at.most(100); + + const output3 = ValueGeneratorFactory.sample().getRange(0, null, 'Long'); + expect(output3).to.be.a('number'); + expect(output3).to.be.at.least(0); + expect(output3).to.be.at.most(Math.pow(2, 32)); + }); + + it('getRange should return an Integer in range', function() { + const output = ValueGeneratorFactory.sample().getRange(0, 100, 'Integer'); + expect(output).to.be.a('number'); + expect(output).to.be.at.least(0); + expect(output).to.be.at.most(100); + + const output2 = ValueGeneratorFactory.sample().getRange(null, 100, 'Integer'); + expect(output2).to.be.a('number'); + expect(output2).to.be.at.least(-Math.pow(2, 16)); + expect(output2).to.be.at.most(100); + + const output3 = ValueGeneratorFactory.sample().getRange(0, null, 'Integer'); + expect(output3).to.be.a('number'); + expect(output3).to.be.at.least(0); + expect(output3).to.be.at.most(Math.pow(2, 16)); + + const output4 = ValueGeneratorFactory.sample().getRange(null, null, 'Integer'); + expect(output4).to.be.a('number'); + expect(output4).to.be.at.least(-Math.pow(2, 16)); + expect(output4).to.be.at.most(Math.pow(2, 16)); + }); + + it('getRange should reverse arguments if range is the wrong way around', function() { + const output = ValueGeneratorFactory.sample().getRange(1.0, 0.0, 'Double'); + expect(output).to.be.a('number'); + expect(output).to.be.at.least(0); + expect(output).to.be.at.most(1); + }); + + it('getRange should return a Double in range', function() { + [ + [0.0, 100.0], + [null, 100.0], + [0.0, null], + [0.0, 0.0], + [null, null], + [6681493, 6681493], + [Infinity, Infinity], + [-Infinity, -Infinity], + [-Infinity, Infinity], + [0.0, Infinity], + ].forEach(([min, max]) => { + const output = ValueGeneratorFactory.sample().getRange(min, max, 'Double'); + expect(output).to.be.a('number'); + const absoluteMax = Math.pow(2, 8); + const atLeastValue = min ? Math.min(Math.max(min, -absoluteMax), absoluteMax): -absoluteMax; + const atMostValue = max ? Math.max(Math.min(max, absoluteMax), -absoluteMax): absoluteMax; + expect(output).to.be.at.least(atLeastValue); + expect(output).to.be.at.most(atMostValue); + }); + }); }); }); diff --git a/packages/concerto-core/types/index.d.ts b/packages/concerto-core/types/index.d.ts index 664c3887cb..61766dcab4 100644 --- a/packages/concerto-core/types/index.d.ts +++ b/packages/concerto-core/types/index.d.ts @@ -73,9 +73,6 @@ declare module '@accordproject/concerto-core' { isEnum(): boolean; isConcept(): boolean; isEvent(): boolean; - isRelationshipTarget(): boolean; - isSystemRelationshipTarget(): boolean; - isSystemType(): boolean; isSystemCoreType(): boolean; getName(): string; getNamespace(): string; @@ -320,11 +317,11 @@ declare module '@accordproject/concerto-core' { private accept(visitor: any, parameters: any): any; validateModelFile(modelFile: string, fileName?: string): void; private _throwAlreadyExists(modelFile: ModelFile): void; - addModelFile(modelFile: string, fileName?: string, disableValidation?: boolean, systemModelTable?: boolean): any; + addModelFile(modelFile: string, fileName?: string, disableValidation?: boolean): any; private getSystemModelTable(): any; updateModelFile(modelFile: string, fileName?: string, disableValidation?: boolean): any; deleteModelFile(namespace: string): void; - addModelFiles(modelFiles: (string|ModelFile)[], fileNames?: string[], disableValidation?: boolean, systemModelTable?: boolean): any[]; + addModelFiles(modelFiles: (string|ModelFile)[], fileNames?: string[], disableValidation?: boolean): any[]; validateModelFiles(): void; updateExternalModels(options?: any, modelFileDownloader?: ModelFileDownloader): Promise; writeModelsToFileSystem(path: string, options?: IncludeModelsOptions): void; diff --git a/packages/concerto-tools/lib/codegen/fromcto/java/javavisitor.js b/packages/concerto-tools/lib/codegen/fromcto/java/javavisitor.js index a7abbdfac1..67cae99087 100644 --- a/packages/concerto-tools/lib/codegen/fromcto/java/javavisitor.js +++ b/packages/concerto-tools/lib/codegen/fromcto/java/javavisitor.js @@ -211,10 +211,6 @@ public abstract class Resource let superType = ''; - if(classDeclaration.isSystemCoreType()) { - superType = ' extends org.hyperledger.composer.system.Resource'; - } - if(classDeclaration.getSuperType()) { superType = ' extends ' + ModelUtil.getShortName(classDeclaration.getSuperType()); } diff --git a/packages/concerto-tools/lib/codegen/fromcto/loopback/loopbackvisitor.js b/packages/concerto-tools/lib/codegen/fromcto/loopback/loopbackvisitor.js index 2d901d6c82..82577ffb2e 100644 --- a/packages/concerto-tools/lib/codegen/fromcto/loopback/loopbackvisitor.js +++ b/packages/concerto-tools/lib/codegen/fromcto/loopback/loopbackvisitor.js @@ -378,14 +378,15 @@ class LoopbackVisitor { }); // For transaction declarations, we need to change the model slightly. - if (classDeclaration instanceof TransactionDeclaration) { - + if (classDeclaration.getIdentifierFieldName()) { // The ID field will be supplied at submission time, not by the client. jsonSchema.forceId = true; const identifierFieldName = classDeclaration.getIdentifierFieldName(); jsonSchema.properties[identifierFieldName].generated = true; jsonSchema.properties[identifierFieldName].required = false; + } + if (classDeclaration instanceof TransactionDeclaration) { // The timestamp can be supplied by the client, but does not have to be. jsonSchema.properties.timestamp.required = false; } diff --git a/packages/concerto-tools/lib/codegen/fromcto/typescript/typescriptvisitor.js b/packages/concerto-tools/lib/codegen/fromcto/typescript/typescriptvisitor.js index 3a49bffbdc..db6f088a63 100644 --- a/packages/concerto-tools/lib/codegen/fromcto/typescript/typescriptvisitor.js +++ b/packages/concerto-tools/lib/codegen/fromcto/typescript/typescriptvisitor.js @@ -89,14 +89,6 @@ class TypescriptVisitor { visitModelFile(modelFile, parameters) { parameters.fileWriter.openFile(modelFile.getNamespace() + '.ts'); - // if this is not the system model file we have to import the system types - // so that they can be extended - if (!modelFile.isSystemModelFile()) { - const systemTypes = modelFile.getModelManager().getSystemTypes(); - systemTypes.forEach(systemType => - parameters.fileWriter.writeLine(0, `import {${systemType.getName()}} from './org.hyperledger.composer.system';`)); - } - // Import property types that are imported from other cto files. const dot = '.'; const properties = new Map(); diff --git a/packages/concerto-tools/lib/codegen/fromcto/xmlschema/xmlschemavisitor.js b/packages/concerto-tools/lib/codegen/fromcto/xmlschema/xmlschemavisitor.js index f009020c1c..94401ae6df 100644 --- a/packages/concerto-tools/lib/codegen/fromcto/xmlschema/xmlschemavisitor.js +++ b/packages/concerto-tools/lib/codegen/fromcto/xmlschema/xmlschemavisitor.js @@ -88,38 +88,24 @@ class XmlSchemaVisitor { parameters.fileWriter.writeLine(0, ''); parameters.fileWriter.writeLine(0, ` { - const systemNamespace = systemModelFile.getNamespace(); - parameters.fileWriter.writeLine(1, `xmlns:${systemNamespace}="${systemNamespace}"`); - importedNamespaces.push(systemNamespace); - }); - for(let importedType of modelFile.getImports()) { - const clazz = modelFile.getModelManager().getType(importedType); - if(importedNamespaces.indexOf(clazz.getNamespace()) === -1){ - importedNamespaces.push(clazz.getNamespace()); - parameters.fileWriter.writeLine(0, `xmlns:${clazz.getNamespace()}="${clazz.getNamespace()}"`); - } + const importedNamespaces = []; + for(let importedType of modelFile.getImports()) { + const clazz = modelFile.getModelManager().getType(importedType); + if(importedNamespaces.indexOf(clazz.getNamespace()) === -1){ + importedNamespaces.push(clazz.getNamespace()); + parameters.fileWriter.writeLine(0, `xmlns:${clazz.getNamespace()}="${clazz.getNamespace()}"`); } } parameters.fileWriter.writeLine(0, '>'); // import the system namespace and then any explicitly required namespaces - if(!modelFile.isSystemModelFile()) { - const importedNamespaces = []; - modelFile.getModelManager().getSystemModelFiles().forEach((systemModelFile) => { - const systemNamespace = systemModelFile.getNamespace(); - parameters.fileWriter.writeLine(0, ``); - importedNamespaces.push(systemNamespace); - }); - // prevent namespaces being imported multiple times - for(let importedType of modelFile.getImports()) { - const clazz = modelFile.getModelManager().getType(importedType); - if(importedNamespaces.indexOf(clazz.getNamespace()) === -1){ - importedNamespaces.push(clazz.getNamespace()); - parameters.fileWriter.writeLine(0, ``); - } + const importedNamespaces2 = []; + // prevent namespaces being imported multiple times + for(let importedType of modelFile.getImports()) { + const clazz = modelFile.getModelManager().getType(importedType); + if(importedNamespaces2.indexOf(clazz.getNamespace()) === -1){ + importedNamespaces2.push(clazz.getNamespace()); + parameters.fileWriter.writeLine(0, ``); } } diff --git a/packages/concerto-tools/lib/codegen/fromjson/cto/inferModel.js b/packages/concerto-tools/lib/codegen/fromjson/cto/inferModel.js new file mode 100644 index 0000000000..8e7bfc579d --- /dev/null +++ b/packages/concerto-tools/lib/codegen/fromjson/cto/inferModel.js @@ -0,0 +1,269 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const Writer = require('@accordproject/concerto-core').Writer; +const TypedStack = require('@accordproject/concerto-core').TypedStack; + +const isoRegex = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/gm; + +function capitalizeFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +function hashCode(value) { + let hash = 0, i, chr; + for (i = 0; i < value.length; i++) { + chr = value.charCodeAt(i); + hash = ((hash << 5) - hash) + chr; + hash |= 0; // Convert to 32bit integer + } + return hash; +} + +/** + * Returns true if val is an object + * @param {*} val the value to test + * @returns {Boolean} true if val is an object + */ +function isObject(val) { + if (val === null) { + return false; + } + return ((typeof val === 'function') || (typeof val === 'object')); +} + +/** + * Returns true if val is a boolean + * @param {*} val the value to test + * @returns {Boolean} true if val is a boolean + */ +function isBoolean(val) { + return val === true || val === false || toString.call(val) === '[object Boolean]'; +} + +/** + * Returns true if val is null + * @param {*} val the value to test + * @returns {Boolean} true if val is null + */ +function isNull(val) { + return val === null; +} + +/** + * Returns true if val is an array + * @param {*} val the value to test + * @returns {Boolean} true if val is an array + */ +function isArray(val) { + return !isNull(val) && Array.isArray(val); +} + +/** + * Returns true if val is a string + * @param {*} val the value to test + * @returns {Boolean} true if val is a string + */ +function isString(val) { + return (typeof val === 'string' || val instanceof String); +} + +/** + * Returns true if val is a date time + * @param {*} val the value to test + * @returns {Boolean} true if val is a string + */ +function isDateTime(val) { + return !isNull(val) && isString(val) && val.match(isoRegex); +} + +/** + * Returns true if val is an integer + * @param {*} val the value to test + * @returns {Boolean} true if val is a string + */ +function isInteger(val) { + if (isNull(val) || isNaN(val) || typeof val !== 'number') { + return false; + } + return val.toString().indexOf('.') === -1; +} + +/** + * Returns true if val is an integer + * @param {*} val the value to test + * @returns {Boolean} true if val is a string + */ +function isDouble(val) { + return (!isNull(val) && !isNaN(val) && typeof val === 'number' && val.toString().indexOf('.') !== -1); +} + +/** + * Handles an array + * @param {*} typeName the name of the type being processed + * @param {*} context the processing context + * @param {*} input the input object + */ +function handleArray(typeName, context, input) { + let result = null; + let item = null; + + if(input.length > 0) { + item = input[0]; + input.forEach( (i) => { + if(isObject(i)) { + item = {...item, ...i}; + } + }); + } + else { + // empty array are assumed to be strings + item = ''; + } + const itemTypeName = isObject(item) ? typeName : getType(item); + + result = handleType(itemTypeName, context, item); + result.array = '[]'; + result.optional = '', + result.name = typeName; + + return result; +} + +/** + * Get the primitive Concerto type for an input + * @param {*} input the input object + */ +function getType(input) { + if (isDouble(input)) { + return 'Double'; + } + else if (isInteger(input)) { + return 'Integer'; + } else if (isBoolean(input)) { + return 'Boolean'; + } else if (isDateTime(input)) { + return 'DateTime'; + } else if (isString(input)) { + return 'String'; + } + else { + // nulls are assumed to be String + return 'String'; + } +} + +/** + * Handles an input type + * @param {*} typeName the name of the type being processed + * @param {*} context the processing context + * @param {*} input the input object + */ +function handleType(name, context, input) { + // console.log(name); + let result = null; + if (isArray(input)) { + result = handleArray(name, context, input); + } else if (isObject(input)) { + const typeDef = { + type: capitalizeFirstLetter(name), + fields : [] + }; + context.parents.push(typeDef); + context[typeDef.type] = typeDef; + const me = context.parents.peek(); + + Object.keys(input).forEach(key => { + const result = handleType(key, context, input[key]); + me.fields.push(result); + }); + me.hash = hashCode(JSON.stringify(me.fields)); + context.parents.pop(); + result = { + name, + type: typeDef.type, + array: '', + optional : '' + }; + } else { + return { + name: name, + type: getType(input), + array: '', + optional : isNull(input) ? 'optional' : '' + }; + } + + return result; +} + +/** + * Detect duplicate types and remove them + * @param {*} context the context + */ +function removeDuplicateTypes(context) { + const typeMap = {}; + Object.values(context).forEach(typeDef => { + if(!typeMap[typeDef.hash]) { + typeMap[typeDef.hash] = typeDef; + } + }); + + Object.values(context).forEach(typeDef => { + Object.values(typeDef.fields).forEach(fieldDef => { + if(context[fieldDef.type]) { + const dupeTypeDef = typeMap[context[fieldDef.type].hash]; + if(dupeTypeDef && fieldDef.type !== dupeTypeDef.type) { + // console.log(`Removed ${fieldDef.type} and replaced with ${dupeTypeDef.type}`); + delete context[fieldDef.type]; + fieldDef.type = dupeTypeDef.type; + } + } + }); + }); + + // console.log(typeMap); +} + +/** + * Infers a Concerto model from a JSON instance. + * @param {string} namespace the namespace to use for the model + * @param {*} rootTypeName the name for the root concept + * @param {*} input the input json object + * @returns {string} the Concerto model + */ +function inferModel(namespace, rootTypeName, input) { + const writer = new Writer(); + + const context = { + parents : new TypedStack() + }; + handleType(rootTypeName, context, input); + delete context.parents; + removeDuplicateTypes(context); + // console.log(JSON.stringify(context, null, 2)); + + writer.writeLine( 0, `namespace ${namespace}`); + Object.values(context).forEach(type => { + writer.writeLine( 0, `concept ${type.type} {`); + type.fields.forEach( field => writer.writeLine( 1, `o ${field.type}${field.array} ${field.name} ${field.optional}`)); + writer.writeLine( 0, '}'); + }); + + return writer.getBuffer(); +} + +module.exports = inferModel; diff --git a/packages/concerto-tools/package.json b/packages/concerto-tools/package.json index 20544b22ec..af4fae725b 100644 --- a/packages/concerto-tools/package.json +++ b/packages/concerto-tools/package.json @@ -121,8 +121,8 @@ "all": true, "check-coverage": true, "statements": 99, - "branches": 97, - "functions": 100, + "branches": 99, + "functions": 99, "lines": 99 } } \ No newline at end of file diff --git a/packages/concerto-tools/test/codegen/fromcto/data/model/circular.cto b/packages/concerto-tools/test/codegen/fromcto/data/model/circular.cto index 35b7e076c3..7557a4c4b4 100755 --- a/packages/concerto-tools/test/codegen/fromcto/data/model/circular.cto +++ b/packages/concerto-tools/test/codegen/fromcto/data/model/circular.cto @@ -33,8 +33,7 @@ participant Par2 identified by id { o String address } -transaction BaseTransaction identified by transactionId { - o String transactionId +transaction BaseTransaction { } transaction UpdateOrderTransaction extends BaseTransaction { @@ -44,8 +43,7 @@ transaction UpdateOrderTransaction extends BaseTransaction { o SomeTransmission transmission } -event UpdateOrderEvent identified by eventId { - o String eventId +event UpdateOrderEvent { --> SomeTransmission transmission } @@ -201,4 +199,4 @@ asset BXBDTL extends SomeMultiple { o String startDate o Long numberOfWeeks o Long spxPerWeek -} \ No newline at end of file +} diff --git a/packages/concerto-tools/test/codegen/fromcto/java/javamissingplugin.js b/packages/concerto-tools/test/codegen/fromcto/java/javamissingplugin.js index c5d015b8b8..8a5338d9de 100644 --- a/packages/concerto-tools/test/codegen/fromcto/java/javamissingplugin.js +++ b/packages/concerto-tools/test/codegen/fromcto/java/javamissingplugin.js @@ -108,7 +108,6 @@ describe('JavaMissingPlugin', function () { }]); mockClassDeclaration.isConcept.returns(false); mockClassDeclaration.isAbstract.returns(false); - mockClassDeclaration.isSystemCoreType.returns(false); mockClassDeclaration.getSuperType.returns(false); mockClassDeclaration.getIdentifierFieldName.returns(false); diff --git a/packages/concerto-tools/test/codegen/fromcto/java/javavisitor.js b/packages/concerto-tools/test/codegen/fromcto/java/javavisitor.js index 26f0ff3c64..0d6d2d35ea 100644 --- a/packages/concerto-tools/test/codegen/fromcto/java/javavisitor.js +++ b/packages/concerto-tools/test/codegen/fromcto/java/javavisitor.js @@ -293,7 +293,6 @@ describe('JavaVisitor', function () { }]); mockClassDeclaration.isConcept.returns(false); mockClassDeclaration.isAbstract.returns(false); - mockClassDeclaration.isSystemCoreType.returns(false); mockClassDeclaration.getSuperType.returns(false); mockClassDeclaration.getIdentifierFieldName.returns(false); @@ -354,7 +353,6 @@ describe('JavaVisitor', function () { }); it('should write a system core type class declaration and call accept on each property', () => { - mockClassDeclaration.isSystemCoreType.returns(true); javaVisit.visitClassDeclaration(mockClassDeclaration, param); @@ -362,7 +360,7 @@ describe('JavaVisitor', function () { param.fileWriter.writeLine.callCount.should.deep.equal(4); param.fileWriter.writeLine.getCall(0).args.should.deep.equal([0, 'import oranges;']); param.fileWriter.writeLine.getCall(1).args.should.deep.equal([0, 'import apples;']); - param.fileWriter.writeLine.getCall(2).args.should.deep.equal([0, 'public class Bob extends org.hyperledger.composer.system.Resource {']); + param.fileWriter.writeLine.getCall(2).args.should.deep.equal([0, 'public class Bob {']); param.fileWriter.writeLine.getCall(3).args.should.deep.equal([0, '}']); acceptSpy.withArgs(javaVisit, Object.assign({},param,{mode:'field'})).calledTwice.should.be.ok; acceptSpy.withArgs(javaVisit, Object.assign({},param,{mode:'getter'})).calledTwice.should.be.ok; diff --git a/packages/concerto-tools/test/codegen/fromcto/loopback/loopbackvisitorcircular.js b/packages/concerto-tools/test/codegen/fromcto/loopback/loopbackvisitorcircular.js index d5d1a6fc5d..7d5541470b 100644 --- a/packages/concerto-tools/test/codegen/fromcto/loopback/loopbackvisitorcircular.js +++ b/packages/concerto-tools/test/codegen/fromcto/loopback/loopbackvisitorcircular.js @@ -38,7 +38,7 @@ describe('LoopbackVisitor with Circular Model', () => { beforeEach(() => { mockFileWriter = sinon.createStubInstance(FileWriter); modelManager = new ModelManager(); - modelManager.addModelFile(fs.readFileSync(path.resolve(__dirname, '../data/model/circular.cto'), 'utf8'), 'model-base.cto'); + modelManager.addModelFile(fs.readFileSync(path.resolve(__dirname, '../data/model/circular.cto'), 'utf8'), 'circular.cto'); visitor = new LoopbackVisitor(namespaces); sandbox = sinon.sandbox.create(); }); diff --git a/packages/concerto-tools/test/codegen/fromcto/typescript/typescriptvisitor.js b/packages/concerto-tools/test/codegen/fromcto/typescript/typescriptvisitor.js index e9f6745e1b..b4b1228317 100644 --- a/packages/concerto-tools/test/codegen/fromcto/typescript/typescriptvisitor.js +++ b/packages/concerto-tools/test/codegen/fromcto/typescript/typescriptvisitor.js @@ -201,7 +201,6 @@ describe('TypescriptVisitor', function () { let mockModelFile = sinon.createStubInstance(ModelFile); mockModelFile._isModelFile = true; - mockModelFile.isSystemModelFile.returns(true); mockModelFile.getNamespace.returns('org.acme.Person'); mockModelFile.getAllDeclarations.returns([ mockEnum, @@ -266,20 +265,9 @@ describe('TypescriptVisitor', function () { let mockModelManager = sinon.createStubInstance(ModelManager); mockModelManager._isModelManager = true; - mockModelManager.getSystemTypes.returns([{ - getName: () => { - return 'Bob'; - } - }, - { - getName: () => { - return 'Fred'; - } - }]); let mockModelFile = sinon.createStubInstance(ModelFile); mockModelFile._isModelFile = true; - mockModelFile.isSystemModelFile.returns(false); mockModelFile.getNamespace.returns('org.acme.Person'); mockModelFile.getAllDeclarations.returns([ mockEnum, @@ -295,12 +283,10 @@ describe('TypescriptVisitor', function () { typescriptVisitor.visitModelFile(mockModelFile, param); param.fileWriter.openFile.withArgs('org.acme.Person.ts').calledOnce.should.be.ok; - param.fileWriter.writeLine.callCount.should.deep.equal(5); - param.fileWriter.writeLine.getCall(0).args.should.deep.equal([0, 'import {Bob} from \'./org.hyperledger.composer.system\';']); - param.fileWriter.writeLine.getCall(1).args.should.deep.equal([0, 'import {Fred} from \'./org.hyperledger.composer.system\';']); - param.fileWriter.writeLine.getCall(2).args.should.deep.equal([0, 'import {Property1,Property3} from \'./org.org1\';']); - param.fileWriter.writeLine.getCall(3).args.should.deep.equal([0, '// export namespace org.acme.Person{']); - param.fileWriter.writeLine.getCall(4).args.should.deep.equal([0, '// }']); + param.fileWriter.writeLine.callCount.should.deep.equal(3); + param.fileWriter.writeLine.getCall(0).args.should.deep.equal([0, 'import {Property1,Property3} from \'./org.org1\';']); + param.fileWriter.writeLine.getCall(1).args.should.deep.equal([0, '// export namespace org.acme.Person{']); + param.fileWriter.writeLine.getCall(2).args.should.deep.equal([0, '// }']); param.fileWriter.closeFile.calledOnce.should.be.ok; acceptSpy.withArgs(typescriptVisitor, param).calledTwice.should.be.ok; diff --git a/packages/concerto-tools/test/codegen/fromcto/xmlschema/xmlschemavisitor.js b/packages/concerto-tools/test/codegen/fromcto/xmlschema/xmlschemavisitor.js index 9c7e6c7339..c77bcffc9c 100644 --- a/packages/concerto-tools/test/codegen/fromcto/xmlschema/xmlschemavisitor.js +++ b/packages/concerto-tools/test/codegen/fromcto/xmlschema/xmlschemavisitor.js @@ -129,24 +129,27 @@ describe('XmlSchemaVisitor', function () { let mockModelFile = sinon.createStubInstance(ModelFile); mockModelFile._isModelFile = true; + mockModelFile.getImports.returns([]); mockModelFile.getModelManager.returns(mockModelManager); mockModelFile.accept = function(visitor, parameters) { return visitor.visit(this, parameters); }; mockModelFile.getNamespace.returns('org.hyperledger.composer.system'); - mockModelFile.isSystemModelFile.returns(true); mockModelFile.getAllDeclarations.returns([mockClassDeclaration]); + mockModelFile.getImports.returns(['org.imported.ImportedType']); mockModelManager.getModelFiles.returns([mockModelFile]); xmlSchemaVisitor.visit(mockModelManager, param); param.fileWriter.openFile.withArgs('org.hyperledger.composer.system.xsd').calledOnce.should.be.ok; - param.fileWriter.writeLine.callCount.should.deep.equal(4); + param.fileWriter.writeLine.callCount.should.deep.equal(6); param.fileWriter.writeLine.getCall(0).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(1).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(3).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(1).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(4).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(5).args.should.deep.equal([0, '']); param.fileWriter.closeFile.calledOnce.should.be.ok; }); @@ -171,6 +174,7 @@ describe('XmlSchemaVisitor', function () { mockModelManager.getType.returns(mockClassDeclaration); let mockModelFile = sinon.createStubInstance(ModelFile); + mockModelFile.getImports.returns([]); mockModelFile._isModelFile = true; mockModelFile.getModelManager.returns(mockModelManager); @@ -178,18 +182,21 @@ describe('XmlSchemaVisitor', function () { return visitor.visit(this, parameters); }; mockModelFile.getNamespace.returns('org.hyperledger.composer.system'); - mockModelFile.isSystemModelFile.returns(true); mockModelFile.getAllDeclarations.returns([mockClassDeclaration]); + mockModelFile.getImports.returns(['org.imported.ImportedType']); + mockModelManager.getModelFiles.returns([mockModelFile]); xmlSchemaVisitor.visitModelManager(mockModelManager, param); param.fileWriter.openFile.withArgs('org.hyperledger.composer.system.xsd').calledOnce.should.be.ok; - param.fileWriter.writeLine.callCount.should.deep.equal(4); + param.fileWriter.writeLine.callCount.should.deep.equal(6); param.fileWriter.writeLine.getCall(0).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(1).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(3).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(1).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(4).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(5).args.should.deep.equal([0, '']); param.fileWriter.closeFile.calledOnce.should.be.ok; }); @@ -206,12 +213,6 @@ describe('XmlSchemaVisitor', function () { return visitor.visit(this, parameters); }; - let mockSystemModelFile = sinon.createStubInstance(ModelFile); - mockSystemModelFile._isModelFile = true; - mockSystemModelFile.getModelManager.returns(mockModelManager); - mockSystemModelFile.isSystemModelFile.returns(true); - mockSystemModelFile.getNamespace.returns('org.hyperledger.composer.system'); - let mockClassDeclaration = sinon.createStubInstance(ClassDeclaration); mockClassDeclaration._isClassDeclaration = true; mockClassDeclaration.getNamespace.returns('org.imported'); @@ -234,7 +235,6 @@ describe('XmlSchemaVisitor', function () { mockModelFile._isModelFile = true; mockModelFile.getModelManager.returns(mockModelManager); - mockModelFile.isSystemModelFile.returns(false); mockModelFile.getImports.returns(['org.imported.ImportedType','org.imported.AnotherImportedType', 'org.different.Type']); mockModelFile.accept = function(visitor, parameters) { @@ -243,22 +243,20 @@ describe('XmlSchemaVisitor', function () { mockModelFile.getNamespace.returns('org.foo'); mockModelFile.getAllDeclarations.returns([mockClassDeclaration]); mockModelManager.getModelFiles.returns([mockModelFile]); - mockModelManager.getSystemModelFiles.returns([mockSystemModelFile]); xmlSchemaVisitor.visitModelManager(mockModelManager, param); param.fileWriter.openFile.withArgs('org.foo.xsd').calledOnce.should.be.ok; - param.fileWriter.writeLine.callCount.should.deep.equal(10); - param.fileWriter.writeLine.getCall(0).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(1).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(6).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(7).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(8).args.should.deep.equal([0, '']); - param.fileWriter.writeLine.getCall(9).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.callCount.should.deep.equal(8); + let index=0; + param.fileWriter.writeLine.getCall(index++).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(index++).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(index++).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(index++).args.should.deep.equal([0, '']); + param.fileWriter.writeLine.getCall(index++).args.should.deep.equal([0, '']); param.fileWriter.closeFile.calledOnce.should.be.ok; }); diff --git a/packages/concerto-tools/test/codegen/fromjson/cto/data/full.cto b/packages/concerto-tools/test/codegen/fromjson/cto/data/full.cto new file mode 100644 index 0000000000..d0e59f620b --- /dev/null +++ b/packages/concerto-tools/test/codegen/fromjson/cto/data/full.cto @@ -0,0 +1,43 @@ +namespace org.acme +concept Root { + o String firstName + o String lastName + o DateTime dob + o Integer age + o Double height + o Children[] children + o Company company +} +concept Children { + o String name + o Integer age + o String hairColor + o Boolean coolDude + o String missing optional + o Pet pet + o String[] favoriteColors + o Integer[] favoriteNumbers + o String[] mixed + o String[] arrayOfNull + o String[] emptyArray + o Pet[] favoritePets + o Stuff[] stuff +} +concept Pet { + o String name + o String breed +} +concept Stuff { + o String ssn + o String firstName + o String sku + o Double price + o Pet product +} +concept Company { + o String name + o Employees[] employees +} +concept Employees { + o String name +} diff --git a/packages/concerto-tools/test/codegen/fromjson/cto/data/full.json b/packages/concerto-tools/test/codegen/fromjson/cto/data/full.json new file mode 100644 index 0000000000..d607bb3eb7 --- /dev/null +++ b/packages/concerto-tools/test/codegen/fromjson/cto/data/full.json @@ -0,0 +1,35 @@ +{ + "firstName":"Dan", + "lastName":"Selman", + "dob":"2011-10-05T14:48:00.000Z", + "age":11, + "height":1.8, + "children":[ + { + "name":"Isaac", + "age":19, + "hairColor":"BROWN", + "coolDude":true, + "missing":null, + "pet":{"name":"Dusty","breed":"Tortoise"}, + "favoriteColors":["red","green","blue"], + "favoriteNumbers":[3,4,5.3], + "mixed":["one",2,3], + "arrayOfNull" : [null], + "emptyArray" : [], + "favoritePets" : [ + {"name":"Spot","breed":"Lab"}, + {"name":"Patch","breed":"Springer"} + ], + "stuff" : [ + 5, + null, + false, + {"ssn":"123456789","firstName":"Dan"}, + {"sku":"987654321","price": 10.0, "product": {"name": "Bella", "breed": "Lab"}}, + {"sku":"2","price": 11.5, "product": {"name": "Tiger", "breed": "Lab"}} + ] + } + ], + "company":{"name":"Clause Inc.","employees":[{"name":"Ann"}]} + } \ No newline at end of file diff --git a/packages/concerto-tools/test/codegen/fromjson/cto/inferModel.js b/packages/concerto-tools/test/codegen/fromjson/cto/inferModel.js new file mode 100644 index 0000000000..7acf88ffa4 --- /dev/null +++ b/packages/concerto-tools/test/codegen/fromjson/cto/inferModel.js @@ -0,0 +1,35 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const chai = require('chai'); +chai.should(); +const sinon = require('sinon'); +const fs = require('fs'); +const path = require('path'); + +const inferModel = require('../../../../lib/codegen/fromjson/cto/inferModel.js'); + +describe('inferModel', function () { + beforeEach(() => { + }); + + it('should generate Concerto', () => { + const json = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../cto/data/full.json'), 'utf8')); + const expectedCto = fs.readFileSync(path.resolve(__dirname, '../cto/data/full.cto'), 'utf8'); + const cto = inferModel('org.acme', 'Root', json); + cto.should.equal(expectedCto); + }); +}); \ No newline at end of file