From 1c43c9f629a6ca938fcd0c50423777df77188ce9 Mon Sep 17 00:00:00 2001 From: Janny Date: Tue, 9 Jul 2019 15:08:57 -0400 Subject: [PATCH 01/72] fix: jsdoc (#385) Signed-off-by: SAMI BETTAYEB --- lib/postgresql.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/postgresql.js b/lib/postgresql.js index 0d7236bb..0a538d8f 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -112,7 +112,7 @@ PostgreSQL.prototype.connect = function(callback) { * @param {Object} [options] Options object * @callback {Function} [callback] The callback after the SQL statement is executed * @param {String|Error} err The error string or object - * @param {Object[]) data The result from the SQL + * @param {Object[]} data The result from the SQL */ PostgreSQL.prototype.executeSQL = function(sql, params, options, callback) { const self = this; From 871374d66a539aa740377ba95d0a5339e0a04710 Mon Sep 17 00:00:00 2001 From: Aidan Harbison Date: Tue, 20 Aug 2019 13:35:31 -0400 Subject: [PATCH 02/72] chore: set package-lock=false in .npmrc Signed-off-by: SAMI BETTAYEB --- .npmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .npmrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..43c97e71 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false From 9fb6c85d76bae212191cce9de1cb05b04fa5fbe5 Mon Sep 17 00:00:00 2001 From: Viktor Shanin Date: Mon, 6 May 2019 05:01:57 +0300 Subject: [PATCH 03/72] Fix Index upgrade Seems like syntax error: - autoupdate not working due to variable is unset - without this change (just comment this line) Indexes was not updated Signed-off-by: SAMI BETTAYEB --- lib/migration.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 1659f9fa..46c0e3f3 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -783,8 +783,7 @@ function mixinMigration(PostgreSQL) { if (identical && siKeys.length > 1) { if (siKeys.length !== i.keys.length) { // lengths differ, obviously non-matching - // ??? orderMatched is not defined and not used anywhere else - // orderMatched = false; + identical = false; } else { siKeys.forEach(function(propName, iter) { identical = identical && self.column(model, propName) === i.keys[iter]; From 8f8b2c7171479e1b09d271cccd3fa47f6a6628ba Mon Sep 17 00:00:00 2001 From: Viktor Shanin Date: Sat, 3 Aug 2019 22:05:38 +0300 Subject: [PATCH 04/72] Extends test structure to cover fix Signed-off-by: SAMI BETTAYEB --- test/postgresql.autoupdate.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/postgresql.autoupdate.test.js b/test/postgresql.autoupdate.test.js index 900a0724..7a0da8ff 100644 --- a/test/postgresql.autoupdate.test.js +++ b/test/postgresql.autoupdate.test.js @@ -512,6 +512,10 @@ describe('autoupdate', function() { 'length': 20, 'id': 1, }, + 'subid': { + 'type': 'int', + 'id': 1, + }, 'customerId': { 'type': 'String', 'length': 20, @@ -600,6 +604,10 @@ describe('autoupdate', function() { 'length': 20, 'id': 1, }, + 'subid': { + 'type': 'int', + 'id': 1, + }, 'customerId': { 'type': 'String', 'length': 20, From 07a6a1a44d46207f72de0674cf6cf791feb540db Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Thu, 19 Sep 2019 10:08:22 -0400 Subject: [PATCH 05/72] 3.8.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: set package-lock=false in .npmrc (Aidan Harbison) * Extends test structure to cover fix (Viktor Shanin) * Fix Index upgrade (Viktor Shanin) * fix: jsdoc (#385) (Janny) * Enable Travis CI integration (Miroslav Bajtoš) * Manually fix remaining linting violations (Miroslav Bajtoš) * Auto-fix linting violations (Miroslav Bajtoš) * Update eslint to ^6.0.1 (Miroslav Bajtoš) * Update dev-dependencies (Miroslav Bajtoš) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 22 ++++++++++++++++++++++ package.json | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 2e06e675..1ce78c4e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,25 @@ +2019-09-19, Version 3.8.0 +========================= + + * chore: set package-lock=false in .npmrc (Aidan Harbison) + + * Extends test structure to cover fix (Viktor Shanin) + + * Fix Index upgrade (Viktor Shanin) + + * fix: jsdoc (#385) (Janny) + + * Enable Travis CI integration (Miroslav Bajtoš) + + * Manually fix remaining linting violations (Miroslav Bajtoš) + + * Auto-fix linting violations (Miroslav Bajtoš) + + * Update eslint to ^6.0.1 (Miroslav Bajtoš) + + * Update dev-dependencies (Miroslav Bajtoš) + + 2019-06-26, Version 3.7.0 ========================= diff --git a/package.json b/package.json index 3941fdeb..b72ccf70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "3.7.0", + "version": "3.8.0", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=8" From 036e01d35498257196c03eb52fbd6504802037bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 5 Nov 2019 13:15:55 +0100 Subject: [PATCH 06/72] chore: exclude "good first issues" from stalebot Signed-off-by: SAMI BETTAYEB --- .github/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/stale.yml b/.github/stale.yml index bebe60a1..186e4581 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -9,6 +9,7 @@ exemptLabels: - critical - p1 - major + - good first issue # Label to use when marking an issue as stale staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable From cfd069b67d126797fdcbe7ff1b20d6b9330166eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 1 Nov 2019 16:31:42 +0100 Subject: [PATCH 07/72] Fix eslint violations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run `eslint --fix .` to add trailing commas to function arguments. Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- lib/migration.js | 2 +- test/postgresql.migration.test.js | 2 +- test/postgresql.test.js | 8 ++++---- test/postgresql.timestamp.test.js | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 46c0e3f3..d682a8af 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -157,7 +157,7 @@ function mixinMigration(PostgreSQL) { propNames.forEach(function(propName) { if (self.id(model, propName)) return; const found = self.searchForPropertyInActual( - model, self.column(model, propName), actualFields + model, self.column(model, propName), actualFields, ); if (!found && self.propertyHasNotBeenDeleted(model, propName)) { sql.push('ADD COLUMN ' + self.addPropertyToActual(model, propName)); diff --git a/test/postgresql.migration.test.js b/test/postgresql.migration.test.js index 94f58850..4c432cd1 100644 --- a/test/postgresql.migration.test.js +++ b/test/postgresql.migration.test.js @@ -150,7 +150,7 @@ function getIndexes(model, cb) { }); } cb(err, indexes); - } + }, ); } diff --git a/test/postgresql.test.js b/test/postgresql.test.js index 0120ad40..83c80b28 100644 --- a/test/postgresql.test.js +++ b/test/postgresql.test.js @@ -153,7 +153,7 @@ describe('postgresql connector', function() { p.created.getTime().should.be.eql(created.getTime()); done(); }); - } + }, ); }); @@ -169,7 +169,7 @@ describe('postgresql connector', function() { results.should.have.property('affectedRows', 1); done(err); }); - } + }, ); }); @@ -186,7 +186,7 @@ describe('postgresql connector', function() { results.rows[0].id.should.eql(post.id); done(err); }); - } + }, ); }); @@ -212,7 +212,7 @@ describe('postgresql connector', function() { p.should.have.property('approved', false); done(); }); - } + }, ); }); diff --git a/test/postgresql.timestamp.test.js b/test/postgresql.timestamp.test.js index 7d7ca379..0fd2123e 100644 --- a/test/postgresql.timestamp.test.js +++ b/test/postgresql.timestamp.test.js @@ -56,7 +56,7 @@ describe('Timestamps', function() { should.not.exist(err); should.exist(p); done(); - } + }, ); }); From f4ed37f212936de66382f132e0ad24e2085167ee Mon Sep 17 00:00:00 2001 From: Nora Date: Fri, 15 Nov 2019 11:52:06 -0500 Subject: [PATCH 08/72] chore: improve issue and PR templates Signed-off-by: SAMI BETTAYEB --- .github/ISSUE_TEMPLATE.md | 37 ----------------- .github/ISSUE_TEMPLATE/Bug_report.md | 50 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/Feature_request.md | 25 ++++++++++++ .github/ISSUE_TEMPLATE/Question.md | 27 ++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 11 +++++ .github/PULL_REQUEST_TEMPLATE.md | 29 +++++-------- 6 files changed, 124 insertions(+), 55 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/Bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/Feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/Question.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 795176c4..00000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,37 +0,0 @@ - - -# Description/Steps to reproduce - - - -# Link to reproduction sandbox - - - -# Expected result - - - -# Additional information - - diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 00000000..6bc732aa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,50 @@ +--- +name: Bug report +about: Create a report to help us improve +labels: bug + +--- + + + +## Steps to reproduce + + + +## Current Behavior + + + +## Expected Behavior + + + +## Link to reproduction sandbox + + + +## Additional information + + + +## Related Issues + + + +_See [Reporting Issues](http://loopback.io/doc/en/contrib/Reporting-issues.html) for more tips on writing good issues_ diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 00000000..1fd76bad --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,25 @@ +--- +name: Feature request +about: Suggest an idea for this project +labels: feature + +--- + +## Suggestion + + + +## Use Cases + + + +## Examples + + + +## Acceptance criteria + +TBD - will be filled by the team. diff --git a/.github/ISSUE_TEMPLATE/Question.md b/.github/ISSUE_TEMPLATE/Question.md new file mode 100644 index 00000000..eb25195a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Question.md @@ -0,0 +1,27 @@ +--- +name: Question +about: The issue tracker is not for questions. Please use Stack Overflow or other resources for help. +labels: question + +--- + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..92047460 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Report a security vulnerability + url: https://loopback.io/doc/en/contrib/Reporting-issues.html#security-issues + about: Do not report security vulnerabilities using GitHub issues. Please send an email to `reachsl@us.ibm.com` instead. + - name: Get help on StackOverflow + url: https://stackoverflow.com/tags/loopbackjs + about: Please ask and answer questions on StackOverflow. + - name: Join our mailing list + url: https://groups.google.com/forum/#!forum/loopbackjs + about: You can also post your question to our mailing list. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 368cb4cf..3547aefd 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,25 +1,18 @@ -### Description - - -#### Related issues - +Include references to all related GitHub issues and other pull requests, for example: -- connect to +Fixes #123 +Implements #254 +See also #23 +--> -### Checklist +## Checklist - +👉 [Read and sign the CLA (Contributor License Agreement)](https://cla.strongloop.com/agreements/strongloop/loopback-connector-postgresql) 👈 +- [ ] `npm test` passes on your machine - [ ] New tests added or existing tests modified to cover all changes -- [ ] Code conforms with the [style - guide](http://loopback.io/doc/en/contrib/style-guide.html) +- [ ] Code conforms with the [style guide](https://loopback.io/doc/en/contrib/style-guide-es6.html) +- [ ] Commit messages are following our [guidelines](https://loopback.io/doc/en/contrib/git-commit-messages.html) From a7a538a74ea8d9dd55e17c535bacacc313a7f1ca Mon Sep 17 00:00:00 2001 From: Stefano Pirra Date: Tue, 3 Sep 2019 09:58:32 +0200 Subject: [PATCH 09/72] Handler for with(out) time zone time(stamp) types Signed-off-by: SAMI BETTAYEB --- README.md | 2 +- lib/discovery.js | 4 ++++ test/postgresql.discover.test.js | 24 ++++++++++++++++++++++++ test/postgresql.timestamp.test.js | 26 +++++++++++++++++++++++++- test/schema.sql | 14 ++++++++------ 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f23dd813..fa7765cb 100644 --- a/README.md +++ b/README.md @@ -359,7 +359,7 @@ See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for de Number - DATE
TIMESTAMP
TIME + DATE
TIMESTAMP
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITHOUT TIME ZONE
TIMETIME WITH TIME ZONETIME WITHOUT TIME ZONE Date diff --git a/lib/discovery.js b/lib/discovery.js index a29343f3..17a33c80 100644 --- a/lib/discovery.js +++ b/lib/discovery.js @@ -353,7 +353,11 @@ function mixinDiscovery(PostgreSQL) { return 'Number'; case 'DATE': case 'TIMESTAMP': + case 'TIMESTAMP WITHOUT TIME ZONE': + case 'TIMESTAMP WITH TIME ZONE': case 'TIME': + case 'TIME WITHOUT TIME ZONE': + case 'TIME WITH TIME ZONE': return 'Date'; case 'POINT': return 'GeoPoint'; diff --git a/test/postgresql.discover.test.js b/test/postgresql.discover.test.js index 3bf13237..eb32c5dc 100644 --- a/test/postgresql.discover.test.js +++ b/test/postgresql.discover.test.js @@ -327,6 +327,30 @@ describe('Discover LDL schema from a table', function() { }); }); +describe('Discover and map correctly database types', function() { + it('should handle character varying, date, timestamp with time zone, timestamp without time zone', function(done) { + db.discoverSchema('customer', {owner: 'strongloop'}, function(err, schema) { + if (err) { + console.error(err); + done(err); + } else { + assert(schema.properties.username); + assert(schema.properties.username.type === 'String'); + assert(schema.properties.dateofbirth); + assert(schema.properties.dateofbirth.type === 'Date'); + assert(schema.properties.dateofbirth.postgresql.dataType === 'date'); + assert(schema.properties.lastlogin); + assert(schema.properties.lastlogin.type === 'Date'); + assert(schema.properties.lastlogin.postgresql.dataType === 'timestamp with time zone'); + assert(schema.properties.created); + assert(schema.properties.created.type === 'Date'); + assert(schema.properties.created.postgresql.dataType === 'timestamp without time zone'); + done(); + } + }); + }); +}); + describe('Discover and build models', function() { it('should build a model from discovery', function(done) { db.discoverAndBuildModels('GeoPoint', {schema: 'strongloop'}, function(err, schema) { diff --git a/test/postgresql.timestamp.test.js b/test/postgresql.timestamp.test.js index 0fd2123e..ec6ccaa8 100644 --- a/test/postgresql.timestamp.test.js +++ b/test/postgresql.timestamp.test.js @@ -26,6 +26,13 @@ describe('Timestamps', function() { dbDefault: 'now()', }, }, + timestampWithTypeNoZone: { + type: 'Date', + postgresql: { + dataType: 'TIMESTAMP WITHOUT TIME ZONE', + dbDefault: 'now()', + }, + }, timestampWithPrecision: { type: 'Date', postgresql: { @@ -52,7 +59,24 @@ describe('Timestamps', function() { it('create instance', function(done) { PostWithTimestamps.create( - {timestampFromJs: new Date()}, function(err, p) { + { + timestampDefault: new Date, + timestampWithType: new Date, + timestampWithTypeNoZone: new Date, + timestampWithPrecision: new Date, + timestampFromJs: new Date, + + }, function(err, p) { + should.not.exist(err); + should.exist(p); + done(); + }, + ); + }); + + it('should handle default value on creation', function(done) { + PostWithTimestamps.create( + {timestampWithTypeNoZone: new Date()}, function(err, p) { should.not.exist(err); should.exist(p); done(); diff --git a/test/schema.sql b/test/schema.sql index dfb0eea4..ad6e1aaf 100644 --- a/test/schema.sql +++ b/test/schema.sql @@ -303,8 +303,10 @@ CREATE TABLE customer ( credentials character varying(1024), challenges character varying(1024), status character varying(1024), - created date, - lastupdated date + dateofbirth date, + lastlogin timestamp with time zone, + created timestamp without time zone, + lastupdated timestamp without time zone ); @@ -574,10 +576,10 @@ SELECT pg_catalog.setval('"GeoPoint_id_seq"', 2, true); -- Data for Name: customer; Type: TABLE DATA; Schema: strongloop; Owner: strongloop -- -INSERT INTO customer VALUES ('612', 'bat', 'bat@bar.com', '$2a$10$BEG18wcYQn7TRkFIc59EB.vmnsEwqJWMlYM4DNG73iZb.MKA1rjAC', NULL, NULL, NULL, NULL, NULL, '[]', '[]', NULL, NULL, NULL); -INSERT INTO customer VALUES ('613', 'baz', 'baz@bar.com', '$2a$10$jkSYF2gLMdI4CwVQh8AStOs0b24lDu9p8jccnmri/0rvhtwsicm9C', NULL, NULL, NULL, NULL, NULL, '[]', '[]', NULL, NULL, NULL); -INSERT INTO customer VALUES ('610', 'foo', 'foo@bar.com', '$2a$10$tn1hN7Xv6x74cCB7tVfwkeaaJTd4/6q4RbCMzgmAJeWe40xqrRSui', NULL, NULL, NULL, NULL, NULL, '[]', '[]', NULL, NULL, NULL); -INSERT INTO customer VALUES ('611', 'bar', 'bar@bar.com', '$2a$10$a8mCol6d5vQXm6vubqXl8e5V66StEg6E8vzjQqPpoyk95Vm3smpiK', NULL, NULL, NULL, NULL, NULL, '[]', '[]', NULL, NULL, NULL); +INSERT INTO customer VALUES ('612', 'bat', 'bat@bar.com', '$2a$10$BEG18wcYQn7TRkFIc59EB.vmnsEwqJWMlYM4DNG73iZb.MKA1rjAC', NULL, NULL, NULL, NULL, NULL, '[]', '[]', NULL, '1970-01-01', NULL, NULL, NULL); +INSERT INTO customer VALUES ('613', 'baz', 'baz@bar.com', '$2a$10$jkSYF2gLMdI4CwVQh8AStOs0b24lDu9p8jccnmri/0rvhtwsicm9C', NULL, NULL, NULL, NULL, NULL, '[]', '[]', NULL, '1980-02-02', NULL, NULL, NULL); +INSERT INTO customer VALUES ('610', 'foo', 'foo@bar.com', '$2a$10$tn1hN7Xv6x74cCB7tVfwkeaaJTd4/6q4RbCMzgmAJeWe40xqrRSui', NULL, NULL, NULL, NULL, NULL, '[]', '[]', NULL, '1990-10-20', NULL, NULL, NULL); +INSERT INTO customer VALUES ('611', 'bar', 'bar@bar.com', '$2a$10$a8mCol6d5vQXm6vubqXl8e5V66StEg6E8vzjQqPpoyk95Vm3smpiK', NULL, NULL, NULL, NULL, NULL, '[]', '[]', NULL, '2000-12-31', NULL, NULL, NULL); -- From 43a710fb8c8af8794b4c9e41648bf1f23e7b82ae Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Tue, 3 Dec 2019 13:27:20 -0500 Subject: [PATCH 10/72] fix(pool): synchronously release pool connection Rapidly-fired queries can exhaust the pool capability and lead to odd results. In test, we've witnessed "Connection Terminated" flakiness with many fast test suites. This, combined with setting `lazyConnect: true` and `idleTimeoutMillis: 0`, alleviates the issue. Signed-off-by: SAMI BETTAYEB --- lib/postgresql.js | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/lib/postgresql.js b/lib/postgresql.js index 0a538d8f..71b9368b 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -40,9 +40,7 @@ exports.initialize = function initializeDataSource(dataSource, callback) { if (callback) { if (dbSettings.lazyConnect) { - process.nextTick(function() { - callback(); - }); + process.nextTick(callback); } else { dataSource.connecting = true; dataSource.connector.connect(callback); @@ -97,9 +95,9 @@ PostgreSQL.prototype.getDefaultSchemaName = function() { */ PostgreSQL.prototype.connect = function(callback) { const self = this; - self.pg.connect(function(err, client, done) { + self.pg.connect(function(err, client, releaseCb) { self.client = client; - process.nextTick(done); + process.nextTick(releaseCb); callback && callback(err, client); }); }; @@ -123,17 +121,13 @@ PostgreSQL.prototype.executeSQL = function(sql, params, options, callback) { debug('SQL: %s', sql); } - function executeWithConnection(connection, done) { + function executeWithConnection(connection, releaseCb) { connection.query(sql, params, function(err, data) { // if(err) console.error(err); if (err) debug(err); if (data) debugData('%j', data); - if (done) { - process.nextTick(function() { - // Release the connection in next tick - done(err); - }); - } + // Release the connection back to the pool. + if (releaseCb) releaseCb(err); let result = null; if (data) { switch (data.command) { @@ -169,9 +163,9 @@ PostgreSQL.prototype.executeSQL = function(sql, params, options, callback) { // Do not release the connection executeWithConnection(transaction.connection, null); } else { - self.pg.connect(function(err, connection, done) { + self.pg.connect(function(err, connection, releaseCb) { if (err) return callback(err); - executeWithConnection(connection, done); + executeWithConnection(connection, releaseCb); }); } }; From 2c498aeae0c5dcbeb03fdb813bae916d29addf88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 9 Dec 2019 15:40:28 +0100 Subject: [PATCH 11/72] 3.8.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(pool): synchronously release pool connection (Samuel Reed) * Handler for with(out) time zone time(stamp) types (Stefano Pirra) * chore: improve issue and PR templates (Nora) * chore: exclude "good first issues" from stalebot (Miroslav Bajtoš) * Fix eslint violations (Miroslav Bajtoš) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1ce78c4e..b73cd92a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,17 @@ +2019-12-09, Version 3.8.1 +========================= + + * fix(pool): synchronously release pool connection (Samuel Reed) + + * Handler for with(out) time zone time(stamp) types (Stefano Pirra) + + * chore: improve issue and PR templates (Nora) + + * chore: exclude "good first issues" from stalebot (Miroslav Bajtoš) + + * Fix eslint violations (Miroslav Bajtoš) + + 2019-09-19, Version 3.8.0 ========================= diff --git a/package.json b/package.json index b72ccf70..5c28497e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "3.8.0", + "version": "3.8.1", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=8" From 16dd365e33f099d0560b98f2587d517b56e62f02 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Tue, 10 Dec 2019 14:00:20 -0500 Subject: [PATCH 12/72] fix: allow string type id to be auto-generated Signed-off-by: SAMI BETTAYEB --- README.md | 107 ++++++++++++++++++++++++++++-- lib/migration.js | 88 ++++++++++++++++++------ test/postgresql.migration.test.js | 71 +++++++++++++++++++- 3 files changed, 239 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index fa7765cb..9d0aa524 100644 --- a/README.md +++ b/README.md @@ -436,7 +436,58 @@ Foreign key constraints can be defined in the model `options`. Removing or updat If there is a reference to an object being deleted then the `DELETE` will fail. Likewise if there is a create with an invalid FK id then the `POST` will fail. -**Note**: The order of table creation is important. A referenced table must exist before creating a foreign key constraint. +**Note**: The order of table creation is important. A referenced table must exist before creating a foreign key constraint. + +For **LoopBack 4** users, define your models under the `models/` folder as follows: + +`customer.model.ts`: + +```ts +@model() +export class Customer extends Entity { + @property({ + id: true, + type: 'Number', + required: false, + length: 20 + }) + id: number; + + @property({ + type: 'string', + length: 20 + }) + name: string; +} +``` +`order.model.ts`: + +```ts +@model() +export class Order extends Entity { + @property({ + id: true, + type: 'Number', + required: false, + length: 20 + }) + id: number; + + @property({ + type: 'string', + length: 20 + }) + name: string; + + @property({ + type: 'Number', + length: 20 + }) + customerId: number; +} +``` + +For **LoopBack 3** users, you can define your model JSON schema as follows: ```json { @@ -446,7 +497,7 @@ If there is a reference to an object being deleted then the `DELETE` will fail. }, "properties": { "id": { - "type": "String", + "type": "Number", "length": 20, "id": 1 }, @@ -473,12 +524,12 @@ If there is a reference to an object being deleted then the `DELETE` will fail. }, "properties": { "id": { - "type": "String", + "type": "Number", "length": 20, "id": 1 }, "customerId": { - "type": "String", + "type": "Number", "length": 20 }, "description": { @@ -490,6 +541,54 @@ If there is a reference to an object being deleted then the `DELETE` will fail. } ``` +Auto-migrate supports the automatic generation of property values. For PostgreSQL, the default id type is _integer_. If you have `generated: true` in the id property, it generates integers by default: + +```ts +{ + id: true, + type: 'Number', + required: false, + generated: true // enables auto-generation +} +``` + +It is common to use UUIDs as the primary key in PostgreSQL instead of integers. You can enable it with the following settings: + +```ts +{ + id: true, + type: 'String', + required: false, + // settings below are needed + generated: true, + useDefaultIdType: false, + postgresql: { + dataType: 'uuid', + }, +} +``` +The setting uses `uuid-ossp` extension and `uuid_generate_v4()` function as default. + +If you'd like to use other extensions and functions, you can do: + +```ts +{ + id: true, + type: 'String', + required: false, + // settings below are needed + generated: true, + useDefaultIdType: false, + postgresql: { + dataType: 'uuid', + extension: 'myExtension', + defaultFn: 'myuuid' + }, +} +``` + +WARNING: It is the users' responsibility to make sure the provided extension and function are valid. + ## Running tests ### Own instance diff --git a/lib/migration.js b/lib/migration.js index d682a8af..2e16d0cf 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -7,6 +7,7 @@ const SG = require('strong-globalize'); const g = SG(); const async = require('async'); +const chalk = require('chalk'); const debug = require('debug')('loopback:connector:postgresql:migration'); module.exports = mixinMigration; @@ -295,12 +296,33 @@ function mixinMigration(PostgreSQL) { const self = this; const modelDef = this.getModelDefinition(model); const prop = modelDef.properties[propName]; + let result = self.columnDataType(model, propName); + + // checks if dataType is set to uuid + let postgDefaultFn; + let postgType; + const postgSettings = prop.postgresql; + if (postgSettings && postgSettings.dataType) { + postgType = postgSettings.dataType.toUpperCase(); + } + if (prop.generated) { - return 'SERIAL'; + if (result === 'INTEGER') { + return 'SERIAL'; + } else if (postgType === 'UUID') { + if (postgSettings && postgSettings.defaultFn && postgSettings.extension) { + // if user provides their own extension and function + postgDefaultFn = postgSettings.defaultFn; + return result + ' NOT NULL' + ' DEFAULT ' + postgDefaultFn; + } + return result + ' NOT NULL' + ' DEFAULT uuid_generate_v4()'; + } else { + console.log(chalk.red('>>> WARNING: ') + + `auto-generation is not supported for type "${chalk.yellow(prop.type)}". \ + Please add your own function to the table "${chalk.yellow(model)}".`); + } } - let result = self.columnDataType(model, propName); if (!self.isNullable(prop)) result = result + ' NOT NULL'; - result += self.columnDbDefault(model, propName); return result; }; @@ -313,32 +335,53 @@ function mixinMigration(PostgreSQL) { PostgreSQL.prototype.createTable = function(model, cb) { const self = this; const name = self.tableEscaped(model); + const modelDef = this.getModelDefinition(model); + + // collects all extensions needed to be created + let createExtensions; + Object.keys(this.getModelDefinition(model).properties).forEach(function(propName) { + const prop = modelDef.properties[propName]; + + // checks if dataType is set to uuid + const postgSettings = prop.postgresql; + if (postgSettings && postgSettings.dataType && postgSettings.dataType === 'UUID' + && postgSettings.defaultFn && postgSettings.extension) { + createExtensions += 'CREATE EXTENSION IF NOT EXISTS "' + postgSettings.extension + '";'; + } + }); + // default extension + if (!createExtensions) { + createExtensions = 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";'; + } // Please note IF NOT EXISTS is introduced in postgresql v9.3 - self.execute('CREATE SCHEMA ' + + self.execute( + createExtensions + + 'CREATE SCHEMA ' + self.escapeName(self.schema(model)), - function(err) { - if (err && err.code !== '42P06') { - return cb && cb(err); - } - self.execute('CREATE TABLE ' + name + ' (\n ' + - self.propertiesSQL(model) + '\n)', - function(err, info) { - if (err) { - return cb(err, info); + function(err) { + if (err && err.code !== '42P06') { + return cb && cb(err); } - self.addIndexes(model, undefined, function(err) { + self.execute('CREATE TABLE ' + name + ' (\n ' + + self.propertiesSQL(model) + '\n)', + function(err, info) { if (err) { - return cb(err); + return cb(err, info); } - const fkSQL = self.getForeignKeySQL(model, - self.getModelDefinition(model).settings.foreignKeys); - self.addForeignKeys(model, fkSQL, function(err, result) { - cb(err); + self.addIndexes(model, undefined, function(err) { + if (err) { + return cb(err); + } + const fkSQL = self.getForeignKeySQL(model, + self.getModelDefinition(model).settings.foreignKeys); + self.addForeignKeys(model, fkSQL, function(err, result) { + cb(err); + }); }); }); - }); - }); + }, + ); }; PostgreSQL.prototype.buildIndex = function(model, property) { @@ -481,7 +524,7 @@ function mixinMigration(PostgreSQL) { default: case 'String': case 'JSON': - return 'TEXT'; + case 'Uuid': case 'Text': return 'TEXT'; case 'Number': @@ -645,6 +688,7 @@ function mixinMigration(PostgreSQL) { case 'CHARACTER': case 'CHAR': case 'TEXT': + case 'UUID': return 'String'; case 'BYTEA': diff --git a/test/postgresql.migration.test.js b/test/postgresql.migration.test.js index 4c432cd1..fa9ff0da 100644 --- a/test/postgresql.migration.test.js +++ b/test/postgresql.migration.test.js @@ -14,7 +14,7 @@ describe('migrations', function() { before(setup); it('should run migration', function(done) { - db.automigrate('UserDataWithIndexes', done); + db.automigrate(['UserDataWithIndexes', 'OrderData', 'DefaultUuid'], done); }); it('UserDataWithIndexes should have correct indexes', function(done) { @@ -73,6 +73,42 @@ describe('migrations', function() { done(); }); }); + + it('OrderData should have correct prop type uuid with custom generation function', function(done) { + checkColumns('OrderData', function(err, cols) { + assert.deepEqual(cols, { + ordercode: + {column_name: 'ordercode', + column_default: 'uuid_generate_v1()', + data_type: 'uuid'}, + ordername: + {column_name: 'ordername', + column_default: null, + data_type: 'text'}, + id: + {column_name: 'id', + column_default: 'nextval(\'orderdata_id_seq\'::regclass)', + data_type: 'integer'}, + }); + done(); + }); + }); + + it('DefaultUuid should have correct id type uuid and default function v4', function(done) { + checkColumns('DefaultUuid', function(err, cols) { + assert.deepEqual(cols, { + defaultcode: + {column_name: 'defaultcode', + column_default: 'uuid_generate_v4()', + data_type: 'uuid'}, + id: + {column_name: 'id', + column_default: 'nextval(\'defaultuuid_id_seq\'::regclass)', + data_type: 'integer'}, + }); + done(); + }); + }); }); function setup(done) { @@ -118,6 +154,23 @@ function setup(done) { }, }, }); + const OrderData = db.define('OrderData', { + ordercode: {type: 'String', required: true, generated: true, useDefaultIdType: false, + postgresql: { + dataType: 'uuid', + defaultFn: 'uuid_generate_v1()', + extension: 'uuid-ossp', + }}, + ordername: {type: 'String'}, + }); + + const DefaultUuid = db.define('DefaultUuid', { + defaultCode: {type: 'String', required: true, generated: true, useDefaultIdType: false, + postgresql: { + dataType: 'uuid', + defaultFn: 'uuid_generate_v1()', // lack extension + }}, + }); done(); } @@ -161,3 +214,19 @@ function table(model) { function query(sql, cb) { db.adapter.query(sql, cb); } + +function checkColumns(table, cb) { + const tableName = table.toLowerCase(); + query('SELECT column_name, column_default, data_type FROM information_schema.columns \ + WHERE(table_schema, table_name) = (\'public\', \'' + tableName + '\');', + function(err, data) { + const cols = {}; + if (!err) { + data.forEach(function(index) { + cols[index.column_name] = index; + delete index.name; + }); + } + cb(err, cols); + }); +} From c6936787fe486c0741b15cefbaee374619c5b1d9 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Thu, 19 Dec 2019 08:26:27 -0500 Subject: [PATCH 13/72] chore: update CODEOWNERS file Signed-off-by: SAMI BETTAYEB --- CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index c8168433..f26750f7 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -3,7 +3,7 @@ # the last matching pattern has the most precedence. # Alumni members -# @kjdelisle @loay @ssh24 @virkt25 +# @kjdelisle @loay @ssh24 @virkt25 @b-admike @zbarbuto @elv1s # Core team members -* @jannyHou @b-admike @dhmlau @zbarbuto @elv1s +* @jannyHou @dhmlau @emonddr @agnes512 From cf851675947d8b8614cb37c3b3f9d4ab31d5bf5a Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Wed, 29 Jan 2020 13:25:31 -0500 Subject: [PATCH 14/72] fix schema name with pascal case Signed-off-by: SAMI BETTAYEB --- test/postgresql.discover.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/postgresql.discover.test.js b/test/postgresql.discover.test.js index eb32c5dc..a7728c2a 100644 --- a/test/postgresql.discover.test.js +++ b/test/postgresql.discover.test.js @@ -354,7 +354,7 @@ describe('Discover and map correctly database types', function() { describe('Discover and build models', function() { it('should build a model from discovery', function(done) { db.discoverAndBuildModels('GeoPoint', {schema: 'strongloop'}, function(err, schema) { - schema.Geopoint.find(function(err, data) { + schema.GeoPoint.find(function(err, data) { console.log('This is our err: ', err); assert(!err); assert(Array.isArray(data)); From f14fa63734e6e9815d654bca716103837aa547cc Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Fri, 31 Jan 2020 11:08:23 -0500 Subject: [PATCH 15/72] 3.8.2 * fix schema name with pascal case (Agnes Lin) * chore: update CODEOWNERS file (Agnes Lin) * fix: allow string type id to be auto-generated (Agnes Lin) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index b73cd92a..218476d1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,13 @@ +2020-01-31, Version 3.8.2 +========================= + + * fix schema name with pascal case (Agnes Lin) + + * chore: update CODEOWNERS file (Agnes Lin) + + * fix: allow string type id to be auto-generated (Agnes Lin) + + 2019-12-09, Version 3.8.1 ========================= diff --git a/package.json b/package.json index 5c28497e..a9b18d3b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "3.8.1", + "version": "3.8.2", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=8" From fd7cbb10c3cbfe0f4e8966e25f3be453dae9247e Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Fri, 31 Jan 2020 12:42:42 -0500 Subject: [PATCH 16/72] add missing package chalk Signed-off-by: SAMI BETTAYEB --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index a9b18d3b..039fe58f 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "dependencies": { "async": "^0.9.0", "bluebird": "^3.4.6", + "chalk": "^3.0.0", "debug": "^4.1.1", "loopback-connector": "^4.2.2", "pg": "^7.0.0", From 773d43870ed913def6b2be1705ec231443b3070b Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Fri, 31 Jan 2020 13:53:03 -0500 Subject: [PATCH 17/72] 3.8.3 * add missing package chalk (Agnes Lin) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 218476d1..e391e17c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +2020-01-31, Version 3.8.3 +========================= + + * add missing package chalk (Agnes Lin) + + 2020-01-31, Version 3.8.2 ========================= diff --git a/package.json b/package.json index 039fe58f..ce6e2064 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "3.8.2", + "version": "3.8.3", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=8" From 2adc7fcfbab39e62d9888a237311f2404462148d Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Mon, 10 Feb 2020 19:48:30 -0500 Subject: [PATCH 18/72] chore: update copyright year Signed-off-by: SAMI BETTAYEB --- example/app.js | 2 +- example/model.js | 2 +- index.js | 2 +- lib/discovery.js | 2 +- lib/postgresql.js | 2 +- lib/transaction.js | 2 +- pretest.js | 2 +- test/postgresql.autocreateschema.test.js | 2 +- test/postgresql.dbdefaults.test.js | 2 +- test/postgresql.discover.test.js | 2 +- test/postgresql.filterUndefined.test.js | 2 +- test/postgresql.initialization.test.js | 2 +- test/postgresql.mapping.test.js | 2 +- test/postgresql.migration.test.js | 2 +- test/postgresql.timestamp.test.js | 2 +- test/postgresql.transaction.test.js | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/example/app.js b/example/app.js index 3e9c420b..72d61b92 100644 --- a/example/app.js +++ b/example/app.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2013,2016. All Rights Reserved. +// Copyright IBM Corp. 2013,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/example/model.js b/example/model.js index e3d3adb7..f7522d61 100644 --- a/example/model.js +++ b/example/model.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2013,2016. All Rights Reserved. +// Copyright IBM Corp. 2013,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/index.js b/index.js index e519aecf..eaa1df3f 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2013,2016. All Rights Reserved. +// Copyright IBM Corp. 2013,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/lib/discovery.js b/lib/discovery.js index 17a33c80..ed01ca02 100644 --- a/lib/discovery.js +++ b/lib/discovery.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2013,2018. All Rights Reserved. +// Copyright IBM Corp. 2013,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/lib/postgresql.js b/lib/postgresql.js index 71b9368b..022737b4 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2013,2018. All Rights Reserved. +// Copyright IBM Corp. 2013,2020. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/lib/transaction.js b/lib/transaction.js index f676c908..23f21938 100644 --- a/lib/transaction.js +++ b/lib/transaction.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2015,2018. All Rights Reserved. +// Copyright IBM Corp. 2015,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/pretest.js b/pretest.js index a8445fdf..ff5c662c 100644 --- a/pretest.js +++ b/pretest.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2016,2017. All Rights Reserved. +// Copyright IBM Corp. 2016,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.autocreateschema.test.js b/test/postgresql.autocreateschema.test.js index e4805837..1d25075f 100644 --- a/test/postgresql.autocreateschema.test.js +++ b/test/postgresql.autocreateschema.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2015,2016. All Rights Reserved. +// Copyright IBM Corp. 2015,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.dbdefaults.test.js b/test/postgresql.dbdefaults.test.js index dffd0dfa..394863f7 100644 --- a/test/postgresql.dbdefaults.test.js +++ b/test/postgresql.dbdefaults.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2015,2017. All Rights Reserved. +// Copyright IBM Corp. 2015,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.discover.test.js b/test/postgresql.discover.test.js index a7728c2a..2be3e17a 100644 --- a/test/postgresql.discover.test.js +++ b/test/postgresql.discover.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2013,2017. All Rights Reserved. +// Copyright IBM Corp. 2013,2020. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.filterUndefined.test.js b/test/postgresql.filterUndefined.test.js index 5b2b36ec..6e9a42eb 100644 --- a/test/postgresql.filterUndefined.test.js +++ b/test/postgresql.filterUndefined.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2015,2016. All Rights Reserved. +// Copyright IBM Corp. 2015,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.initialization.test.js b/test/postgresql.initialization.test.js index 848e9456..f5a431b6 100644 --- a/test/postgresql.initialization.test.js +++ b/test/postgresql.initialization.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2016,2017. All Rights Reserved. +// Copyright IBM Corp. 2016,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.mapping.test.js b/test/postgresql.mapping.test.js index 463a0039..198cba2a 100644 --- a/test/postgresql.mapping.test.js +++ b/test/postgresql.mapping.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2014,2016. All Rights Reserved. +// Copyright IBM Corp. 2014,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.migration.test.js b/test/postgresql.migration.test.js index fa9ff0da..7d0724c2 100644 --- a/test/postgresql.migration.test.js +++ b/test/postgresql.migration.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2015,2016. All Rights Reserved. +// Copyright IBM Corp. 2015,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.timestamp.test.js b/test/postgresql.timestamp.test.js index ec6ccaa8..453e88d0 100644 --- a/test/postgresql.timestamp.test.js +++ b/test/postgresql.timestamp.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2018. All Rights Reserved. +// Copyright IBM Corp. 2018,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 diff --git a/test/postgresql.transaction.test.js b/test/postgresql.transaction.test.js index 984b8bcf..1dcbdfc3 100644 --- a/test/postgresql.transaction.test.js +++ b/test/postgresql.transaction.test.js @@ -1,4 +1,4 @@ -// Copyright IBM Corp. 2015,2017. All Rights Reserved. +// Copyright IBM Corp. 2015,2019. All Rights Reserved. // Node module: loopback-connector-postgresql // This file is licensed under the Artistic License 2.0. // License text available at https://opensource.org/licenses/Artistic-2.0 From cd56f7a559d7613351e12454bd134522f2be56e1 Mon Sep 17 00:00:00 2001 From: Erik de Groot Date: Mon, 17 Feb 2020 10:13:52 +0100 Subject: [PATCH 19/72] feat: Added defaultIdSort setting for find method Signed-off-by: SAMI BETTAYEB --- lib/postgresql.js | 90 ++++++++++++++ test/postgresql.order.test.js | 228 ++++++++++++++++++++++++++++++++++ 2 files changed, 318 insertions(+) create mode 100644 test/postgresql.order.test.js diff --git a/lib/postgresql.js b/lib/postgresql.js index 022737b4..02495927 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -15,6 +15,7 @@ const ParameterizedSQL = SqlConnector.ParameterizedSQL; const util = require('util'); const debug = require('debug')('loopback:connector:postgresql'); const debugData = require('debug')('loopback:connector:postgresql:data'); +const debugSort = require('debug')('loopback:connector:postgresql:order'); const Promise = require('bluebird'); /** @@ -179,6 +180,95 @@ PostgreSQL.prototype.buildInsertReturning = function(model, data, options) { return 'RETURNING ' + idColumnNames.join(','); }; +/** + * Check if id types have a numeric type + * @param {String} model name + * @returns {Boolean} + */ +PostgreSQL.prototype.hasOnlyNumericIds = function(model) { + const cols = this.getModelDefinition(model).properties; + const idNames = this.idNames(model); + const numericIds = idNames.filter(function(idName) { + return cols[idName].type === Number; + }); + + return numericIds.length == idNames.length; +}; + +/** + * Get default find sort policy + * @param model + */ +PostgreSQL.prototype.getDefaultIdSortPolicy = function(model) { + const modelClass = this._models[model]; + + if (modelClass.settings.hasOwnProperty('defaultIdSort')) { + return modelClass.settings.defaultIdSort; + } + + if (this.settings.hasOwnProperty('defaultIdSort')) { + return this.settings.defaultIdSort; + } + + return null; +}; + +/** + * Build a SQL SELECT statement + * @param {String} model Model name + * @param {Object} filter Filter object + * @param {Object} options Options object + * @returns {ParameterizedSQL} Statement object {sql: ..., params: ...} + */ +PostgreSQL.prototype.buildSelect = function(model, filter) { + let sortById; + + const sortPolicy = this.getDefaultIdSortPolicy(model); + + switch (sortPolicy) { + case 'numericIdOnly': + sortById = this.hasOnlyNumericIds(model); + break; + case false: + sortById = false; + break; + default: + sortById = true; + break; + } + + debugSort(model, 'sort policy:', sortPolicy, sortById); + + if (sortById && !filter.order) { + const idNames = this.idNames(model); + if (idNames && idNames.length) { + filter.order = idNames; + } + } + + let selectStmt = new ParameterizedSQL('SELECT ' + + this.buildColumnNames(model, filter) + + ' FROM ' + this.tableEscaped(model)); + + if (filter) { + if (filter.where) { + const whereStmt = this.buildWhere(model, filter.where); + selectStmt.merge(whereStmt); + } + + if (filter.order) { + selectStmt.merge(this.buildOrderBy(model, filter.order)); + } + + if (filter.limit || filter.skip || filter.offset) { + selectStmt = this.applyPagination( + model, selectStmt, filter, + ); + } + } + return this.parameterize(selectStmt); +}; + PostgreSQL.prototype.buildInsertDefaultValues = function(model, data, options) { return 'DEFAULT VALUES'; }; diff --git a/test/postgresql.order.test.js b/test/postgresql.order.test.js new file mode 100644 index 00000000..907a490b --- /dev/null +++ b/test/postgresql.order.test.js @@ -0,0 +1,228 @@ +// Copyright IBM Corp. 2020. All Rights Reserved. +// Node module: loopback-connector-postgresql +// This file is licensed under the Artistic License 2.0. +// License text available at https://opensource.org/licenses/Artistic-2.0 + +'use strict'; + +require('./init'); +const should = require('should'); +const async = require('async'); + +let db, + PostWithDefaultIdSort, + PostWithDisabledDefaultIdSort, + PostWithNumericDefaultIdSort, + PostWithNumericStringDefaultIdSort; + +describe('Order settings', function() { + before(function() { + db = global.getSchema(); + }); + + before(function(done) { + PostWithDefaultIdSort = db.define( + 'PostWithDefaultIdSort', + { + id: {type: Number, id: true}, + title: {type: String, length: 255, index: true}, + content: {type: String}, + }, + { + defaultIdSort: true, + }, + ); + + PostWithDisabledDefaultIdSort = db.define( + 'PostWithDisabledDefaultIdSort', + { + id: {type: Number, id: true}, + title: {type: String, length: 255, index: true}, + content: {type: String}, + }, + { + defaultIdSort: false, + }, + ); + + PostWithNumericDefaultIdSort = db.define( + 'PostWithNumericDefaultIdSort', + { + id: {type: Number, id: true}, + title: {type: String, length: 255, index: true}, + content: {type: String}, + }, + { + defaultIdSort: 'numericIdOnly', + }, + ); + + PostWithNumericStringDefaultIdSort = db.define( + 'PostWithNumericStringDefaultIdSort', + { + id: {type: String, id: true}, + title: {type: String, length: 255, index: true}, + content: {type: String}, + }, + { + defaultIdSort: 'numericIdOnly', + }, + ); + + done(); + }); + + before(function(done) { + db.automigrate([ + 'PostWithDefaultIdSort', + 'PostWithDisabledDefaultIdSort', + 'PostWithNumericDefaultIdSort', + 'PostWithNumericStringDefaultIdSort'], + done); + }); + + after(function(done) { + async.parallel([ + cb => PostWithDefaultIdSort.destroyAll(cb), + cb => PostWithDisabledDefaultIdSort.destroyAll(cb), + cb => PostWithNumericDefaultIdSort.destroyAll(cb), + cb => PostWithNumericStringDefaultIdSort.destroyAll(cb), + ], done); + }); + + it('builds base query', function(done) { + const res = db.connector.buildSelect('PostWithDefaultIdSort', {}); + const sql = res.sql; + + sql.should.be.equal('SELECT "id","title","content" FROM "public"."postwithdefaultidsort" ORDER BY "id"'); + done(); + }); + + it('builds non-ordering base query', function(done) { + const res = db.connector.buildSelect('PostWithDisabledDefaultIdSort', {}); + const sql = res.sql; + + sql.should.be.equal('SELECT "id","title","content" FROM "public"."postwithdisableddefaultidsort"'); + done(); + }); + + it('builds ordering query based on numericIdOnly setting', function(done) { + const res = db.connector.buildSelect('PostWithNumericDefaultIdSort', {}); + const sql = res.sql; + + sql.should.be.equal('SELECT "id","title","content" FROM "public"."postwithnumericdefaultidsort" ORDER BY "id"'); + done(); + }); + + it('builds non-ordering query based on numericIdOnly setting', function(done) { + const res = db.connector.buildSelect('PostWithNumericStringDefaultIdSort', {}); + const sql = res.sql; + + sql.should.be.equal('SELECT "id","title","content" FROM "public"."postwithnumericstringdefaultidsort"'); + done(); + }); + + it('should return results ordered by id', + function(done) { + PostWithDefaultIdSort.create({id: 5, title: 'c', content: 'CCC'}, function(err, post) { + PostWithDefaultIdSort.create({id: 4, title: 'd', content: 'DDD'}, function(err, post) { + PostWithDefaultIdSort.find({}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(2); + posts[0].id.should.be.equal(4); + + PostWithDefaultIdSort.find({limit: 1, offset: 0}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(1); + posts[0].id.should.be.equal(4); + + PostWithDefaultIdSort.find({limit: 1, offset: 1}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(1); + posts[0].id.should.be.equal(5); + done(); + }); + }); + }); + }); + }); + }); + + it('should return unordered results', + function(done) { + PostWithDisabledDefaultIdSort.create({id: 2, title: 'c', content: 'CCC'}, function(err, post) { + PostWithDisabledDefaultIdSort.create({id: 1, title: 'd', content: 'DDD'}, function(err, post) { + PostWithDisabledDefaultIdSort.find({}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(2); + posts[0].id.should.be.equal(2); + + PostWithDisabledDefaultIdSort.find({limit: 1, offset: 0}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(1); + posts[0].id.should.be.equal(2); + + PostWithDisabledDefaultIdSort.find({limit: 1, offset: 1}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(1); + posts[0].id.should.be.equal(1); + done(); + }); + }); + }); + }); + }); + }); + + it('Should return ordered results by numeric id by default', + function(done) { + PostWithNumericDefaultIdSort.create({id: 12, title: 'c', content: 'CCC'}, function(err, post) { + PostWithNumericDefaultIdSort.create({id: 11, title: 'd', content: 'DDD'}, function(err, post) { + PostWithNumericDefaultIdSort.find({}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(2); + posts[0].id.should.be.equal(11); + + PostWithNumericDefaultIdSort.find({limit: 1, offset: 0}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(1); + posts[0].id.should.be.equal(11); + + PostWithNumericDefaultIdSort.find({limit: 1, offset: 1}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(1); + posts[0].id.should.be.equal(12); + done(); + }); + }); + }); + }); + }); + }); + + it('should return unordered results because of string type id', + function(done) { + PostWithNumericStringDefaultIdSort.create({id: 'b', title: 'c', content: 'CCC'}, function(err, post) { + PostWithNumericStringDefaultIdSort.create({id: 'a', title: 'd', content: 'DDD'}, function(err, post) { + PostWithNumericStringDefaultIdSort.find({}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(2); + posts[0].id.should.be.equal('b'); + + PostWithNumericStringDefaultIdSort.find({limit: 1, offset: 0}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(1); + posts[0].id.should.be.equal('b'); + + PostWithNumericStringDefaultIdSort.find({limit: 1, offset: 1}, function(err, posts) { + should.not.exist(err); + posts.length.should.be.equal(1); + posts[0].id.should.be.equal('a'); + done(); + }); + }); + }); + }); + }); + }); +}); From a3df6828082d536153265819897b22ddd4528bcb Mon Sep 17 00:00:00 2001 From: Erik de Groot Date: Tue, 25 Feb 2020 15:27:02 +0100 Subject: [PATCH 20/72] doc: added readme info on defaultIdSort Signed-off-by: SAMI BETTAYEB --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9d0aa524..c733cf15 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,10 @@ Check out [node-pg-pool](https://github.com/brianc/node-pg-pool) and [node postg Boolean Whether to try SSL/TLS to connect to server + + defaultIdSort + Boolean/String + Set to false to disable default sorting on id column(s). Set to numericIdOnly to only apply to IDs with a number type id. From 2400384a996b03d9f59f60c7d6954d9951ce0e7b Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Tue, 25 Feb 2020 09:04:13 -0800 Subject: [PATCH 21/72] 3.9.0 * doc: added readme info on defaultIdSort (Erik de Groot) * feat: Added defaultIdSort setting for find method (Erik de Groot) * chore: update copyright year (Diana Lau) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 10 ++++++++++ package.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index e391e17c..ac3959d9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,13 @@ +2020-02-25, Version 3.9.0 +========================= + + * doc: added readme info on defaultIdSort (Erik de Groot) + + * feat: Added defaultIdSort setting for find method (Erik de Groot) + + * chore: update copyright year (Diana Lau) + + 2020-01-31, Version 3.8.3 ========================= diff --git a/package.json b/package.json index ce6e2064..473d9d87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "3.8.3", + "version": "3.9.0", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=8" From 45b08e931da083de6a386c62d931e06c90c3b3b4 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Thu, 13 Feb 2020 09:57:57 -0500 Subject: [PATCH 22/72] fix postgres random ci failure Signed-off-by: SAMI BETTAYEB --- test/postgresql.autoupdate.test.js | 183 ++++++----------------------- 1 file changed, 37 insertions(+), 146 deletions(-) diff --git a/test/postgresql.autoupdate.test.js b/test/postgresql.autoupdate.test.js index 7a0da8ff..b1a75ce7 100644 --- a/test/postgresql.autoupdate.test.js +++ b/test/postgresql.autoupdate.test.js @@ -296,8 +296,6 @@ describe('autoupdate', function() { keys: ['firstname'], order: ['ASC']}, }); - - // console.log(err, result); done(err, result); }); }); @@ -419,77 +417,7 @@ describe('autoupdate', function() { }, }; - const customer3_schema = { - 'name': 'CustomerTest3', - 'options': { - 'idInjection': false, - 'postgresql': { - 'schema': 'myapp_test', - 'table': 'customer_test3', - }, - }, - 'properties': { - 'id': { - 'type': 'String', - 'length': 20, - 'id': 1, - }, - 'name': { - 'type': 'String', - 'required': false, - 'length': 40, - }, - 'email': { - 'type': 'String', - 'required': true, - 'length': 40, - }, - 'age': { - 'type': 'Number', - 'required': false, - }, - }, - }; - const orderTest_schema_v1 = { - 'name': 'OrderTest', - 'options': { - 'idInjection': false, - 'postgresql': { - 'schema': 'myapp_test', - 'table': 'order_test', - }, - 'foreignKeys': { - 'fk_ordertest_customerId': { - 'name': 'fk_ordertest_customerId', - 'entity': 'CustomerTest3', - 'entityKey': 'id', - 'foreignKey': 'customerId', - }, - }, - }, - 'properties': { - 'id': { - 'type': 'String', - 'length': 20, - 'id': 1, - }, - 'customerId': { - 'type': 'String', - 'length': 20, - 'postgresql': { - 'columnName': 'customerId', - }, - }, - 'description': { - 'type': 'String', - 'required': false, - 'length': 40, - }, - }, - }; - - const orderTest_schema_v2 = { 'name': 'OrderTest', 'options': { 'idInjection': false, @@ -512,10 +440,6 @@ describe('autoupdate', function() { 'length': 20, 'id': 1, }, - 'subid': { - 'type': 'int', - 'id': 1, - }, 'customerId': { 'type': 'String', 'length': 20, @@ -528,17 +452,10 @@ describe('autoupdate', function() { 'required': false, 'length': 40, }, - 'productId': { - 'type': 'String', - 'length': 20, - 'postgresql': { - 'columnName': 'productId', - }, - }, }, }; - const orderTest_schema_v3 = { + const orderTest_schema_v2 = { 'name': 'OrderTest', 'options': { 'idInjection': false, @@ -547,12 +464,6 @@ describe('autoupdate', function() { 'table': 'order_test', }, 'foreignKeys': { - 'fk_ordertest_customerId': { - 'name': 'fk_ordertest_customerId', - 'entity': 'CustomerTest2', - 'entityKey': 'id', - 'foreignKey': 'customerId', - }, 'fk_ordertest_productId': { 'name': 'fk_ordertest_productId', 'entity': 'Product', @@ -589,7 +500,7 @@ describe('autoupdate', function() { }, }; - const orderTest_schema_v4 = { + const orderTest_schema_v3 = { 'name': 'OrderTest', 'options': { 'idInjection': false, @@ -630,9 +541,7 @@ describe('autoupdate', function() { }, }; - ds.createModel(product_schema.name, product_schema.properties, product_schema.options); ds.createModel(customer2_schema.name, customer2_schema.properties, customer2_schema.options); - ds.createModel(customer3_schema.name, customer3_schema.properties, customer3_schema.options); // Table create order is important. Referenced tables must exist before creating a reference. // do initial update/creation of referenced tables @@ -642,7 +551,11 @@ describe('autoupdate', function() { return done(err); } + // do initial update/creation of of referenced tables for the next step + // model OrderTest has a fk refers to model CustomerTest2 + ds.createModel(product_schema.name, product_schema.properties, product_schema.options); // do initial update/creation of table with fk + // model OrderTest has a fk refers to model CustomerTest2 ds.createModel(orderTest_schema_v1.name, orderTest_schema_v1.properties, orderTest_schema_v1.options); ds.autoupdate(function(err) { if (err) { @@ -662,70 +575,48 @@ describe('autoupdate', function() { assert(foreignKeys); assert.equal(foreignKeys.length, 1); assert.equal(foreignKeys[0].pkColumnName, 'id'); - assert.equal(foreignKeys[0].pkTableName, 'customer_test3'); + assert.equal(foreignKeys[0].pkTableName, 'customer_test2'); assert.equal(foreignKeys[0].fkColumnName, 'customerId'); assert.equal(foreignKeys[0].fkName, 'fk_ordertest_customerId'); - // update and add another fk - ds.createModel(orderTest_schema_v2.name, orderTest_schema_v2.properties, orderTest_schema_v2.options); + // update the fk of model OrderTest from customerId to productId + // productId refers to model Product + ds.createModel(orderTest_schema_v2.name, orderTest_schema_v2.properties, + orderTest_schema_v2.options); ds.autoupdate(function(err) { if (err) { err.message += ' (while updating OrderTest schema v2)'; return done(err); } - ds.discoverModelProperties('order_test', function(err, props) { + // get the foreign keys for order_test + ds.connector.discoverForeignKeys('order_test', {}, function(err, foreignKeys) { if (err) return done(err); - // validate that we have the correct number of properties - assert.equal(props.length, 4); - - // get the foreign keys for order_test - ds.connector.discoverForeignKeys('order_test', {}, function(err, foreignKeysUpdated) { - if (err) return done(err); - // validate that the foreign keys exist and point to the new column - assert(foreignKeysUpdated); - assert.equal(foreignKeysUpdated.length, 1); - assert.equal(foreignKeysUpdated[0].pkColumnName, 'id'); - assert.equal(foreignKeysUpdated[0].pkTableName, 'customer_test2'); - assert.equal(foreignKeysUpdated[0].fkColumnName, 'customerId'); - assert.equal(foreignKeysUpdated[0].fkName, 'fk_ordertest_customerId'); - - // create multiple fks on object - ds.createModel(orderTest_schema_v3.name, orderTest_schema_v3.properties, - orderTest_schema_v3.options); - ds.autoupdate(function(err) { - if (err) { - err.message += ' (while updating OrderTest schema v3)'; - return done(err); - } + assert(foreignKeys); + assert.equal(foreignKeys.length, 1); + assert.equal(foreignKeys[0].pkTableName, 'product_test'); + assert.equal(foreignKeys[0].fkColumnName, 'productId'); + assert.equal(foreignKeys[0].fkName, 'fk_ordertest_productId'); + + // remove fk from model OrderTest + ds.createModel(orderTest_schema_v3.name, orderTest_schema_v3.properties, + orderTest_schema_v3.options); + ds.autoupdate(function(err) { + if (err) { + err.message += ' (while updating OrderTest schema v3)'; + return done(err); + } + ds.discoverModelProperties('order_test', function(err, props) { + if (err) return done(err); + + // validate that we have the correct number of properties + assert.equal(props.length, 4); + // get the foreign keys for order_test - ds.connector.discoverForeignKeys('order_test', {}, function(err, foreignKeysMulti) { + ds.connector.discoverForeignKeys('order_test', {}, function(err, foreignKeysEmpty) { if (err) return done(err); - assert(foreignKeysMulti); - assert.equal(foreignKeysMulti.length, 2); - - // remove fk - ds.createModel(orderTest_schema_v4.name, orderTest_schema_v4.properties, - orderTest_schema_v4.options); - ds.autoupdate(function(err) { - if (err) { - err.message += ' (while updating OrderTest schema v4)'; - return done(err); - } - ds.discoverModelProperties('order_test', function(err, props) { - if (err) return done(err); - - // validate that we have the correct number of properties - assert.equal(props.length, 4); - - // get the foreign keys for order_test - ds.connector.discoverForeignKeys('order_test', {}, function(err, foreignKeysEmpty) { - if (err) return done(err); - assert(foreignKeysEmpty); - assert.equal(foreignKeysEmpty.length, 0); - done(); - }); - }); - }); + assert(foreignKeysEmpty); + assert.equal(foreignKeysEmpty.length, 0); + done(); }); }); }); From 2fe9afd35ebda6f804558c688158c946cadd4a90 Mon Sep 17 00:00:00 2001 From: DEEPAK RAJAMOHAN Date: Wed, 26 Feb 2020 14:35:29 -0800 Subject: [PATCH 23/72] fix: `DEFAULT` for null values in where clause Signed-off-by: SAMI BETTAYEB --- lib/postgresql.js | 12 +++--- test/postgresql.filterUndefined.test.js | 53 ++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/lib/postgresql.js b/lib/postgresql.js index 02495927..b4c62baf 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -644,10 +644,10 @@ PostgreSQL.prototype._buildWhere = function(model, where) { if (Array.isArray(expression)) { // Column value is a list for (let j = 0, m = expression.length; j < m; j++) { - columnValue.push(this.toColumnValue(p, expression[j])); + columnValue.push(this.toColumnValue(p, expression[j], true)); } } else { - columnValue.push(this.toColumnValue(p, expression)); + columnValue.push(this.toColumnValue(p, expression, true)); } if (operator === 'between') { // BETWEEN v1 AND v2 @@ -669,7 +669,7 @@ PostgreSQL.prototype._buildWhere = function(model, where) { // do not coerce RegExp based on property definitions columnValue = expression; } else { - columnValue = this.toColumnValue(p, expression); + columnValue = this.toColumnValue(p, expression, true); } sqlExp = self.buildExpression(columnName, operator, columnValue, p); stmt.merge(sqlExp); @@ -711,13 +711,15 @@ PostgreSQL.prototype._buildWhere = function(model, where) { * Convert property name/value to an escaped DB column value * @param {Object} prop Property descriptor * @param {*} val Property value + * @param {boolean} isWhereClause * @returns {*} The escaped value of DB column */ -PostgreSQL.prototype.toColumnValue = function(prop, val) { +PostgreSQL.prototype.toColumnValue = function(prop, val, isWhereClause) { if (val == null) { // PostgreSQL complains with NULLs in not null columns // If we have an autoincrement value, return DEFAULT instead - if (prop.autoIncrement || prop.id) { + // Do not return 'DEFAULT' for id field in where clause + if (prop.autoIncrement || (prop.id && !isWhereClause)) { return new ParameterizedSQL('DEFAULT'); } else { return null; diff --git a/test/postgresql.filterUndefined.test.js b/test/postgresql.filterUndefined.test.js index 6e9a42eb..01b3bd1e 100644 --- a/test/postgresql.filterUndefined.test.js +++ b/test/postgresql.filterUndefined.test.js @@ -6,7 +6,7 @@ 'use strict'; const should = require('should'), assert = require('assert'); -let Post, db; +let Post, db, Charge, Currency; describe('filter undefined fields', function() { before(function() { @@ -136,4 +136,55 @@ describe('filter undefined fields', function() { }); }); }); + + describe('able to handle null foreign keys', function() { + before(function(done) { + Charge = db.define('Charge', {amount: Number}); + Currency = db.define('Currency', {code: String, country: String}); + Charge.belongsTo('Currency', {as: 'currency'}); + db.automigrate(['Charge', 'Currency'], done); + }); + + it('able to create entity with null foreign key', function(done) { + Currency.create({code: 'USD', country: 'USA'}, function(err, currency) { + if (err) return done(err); + Charge.create({amount: 10, currencyId: currency.id}, function(err) { + if (err) return done(err); + Charge.create({amount: 10, currencyId: null}, function(err, charge) { + if (err) return done(err); + should.not.exist(charge.currencyId); + done(); + }); + }); + }); + }); + + it('able to query entities with null foreign key', function(done) { + Charge.find({ + where: {currency: { + inq: [null, 1], + }}, + include: {relation: 'currency'}, + }, function(err, charges) { + if (err) return done(err); + charges.should.have.lengthOf(2); + done(); + }); + }); + + it('able to filter entities with null id condition', function(done) { + Currency.find({ + where: { + id: { + inq: [null, 1], + }, + }, + }, + function(err, currencies) { + if (err) return done(err); + currencies.should.have.lengthOf(1); + done(); + }); + }); + }); }); From ba5149b830ede070333846209c0e066f07e80c44 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Thu, 5 Mar 2020 09:57:57 -0500 Subject: [PATCH 24/72] tests: column should be discovered and mapped Signed-off-by: SAMI BETTAYEB --- package.json | 2 +- test/postgresql.discover.test.js | 58 ++++++++++++++++++++++++++++++++ test/schema.sql | 6 ++-- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 473d9d87..7fd6c74f 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "bluebird": "^3.4.6", "chalk": "^3.0.0", "debug": "^4.1.1", - "loopback-connector": "^4.2.2", + "loopback-connector": "^4.10.2", "pg": "^7.0.0", "strong-globalize": "^4.0.0", "uuid": "^3.0.1" diff --git a/test/postgresql.discover.test.js b/test/postgresql.discover.test.js index 2be3e17a..ae087a5c 100644 --- a/test/postgresql.discover.test.js +++ b/test/postgresql.discover.test.js @@ -8,6 +8,7 @@ process.env.NODE_ENV = 'test'; require('should'); const assert = require('assert'); +const should = require('should'); const _ = require('lodash'); const DataSource = require('loopback-datasource-juggler').DataSource; @@ -239,6 +240,36 @@ describe('Discover model properties', function() { }); describe('Discover model primary keys', function() { + let Demo; + before(function(done) { + const demo_schema = { + 'name': 'Demo', + 'options': { + 'idInjection': false, + 'postgresql': { + 'schema': 'public', + 'table': 'demo', + }, + }, + 'properties': { + 'id': { + 'type': 'Number', + 'required': true, + 'id': 1, + 'postgresql': { + 'columnName': 'demoId', + }, + }, + 'name': { + 'type': 'String', + 'required': true, + }, + }, + }; + Demo = db.createModel(demo_schema.name, demo_schema.properties, demo_schema.options); + Demo.destroyAll(done); + }); + it('should return an array of primary keys for product', function(done) { db.discoverPrimaryKeys('product', function(err, models) { if (err) { @@ -257,6 +288,33 @@ describe('Discover model primary keys', function() { }); }); + it('primary key should be discovered, and db generates instances properly', function(done) { + db.discoverPrimaryKeys('demo', function(err, models) { + if (err) { + console.error(err); + done(err); + } else { + models.forEach(function(m) { + assert.deepEqual(m, {owner: 'public', + tableName: 'demo', + columnName: 'demoId', + keySeq: 1, + pkName: 'demo_pkey'}); + }); + } + }); + Demo.create({id: 1, name: 'checkCase'}, function(err) { + should.not.exists(err); + Demo.findOne({}, function(err, d) { + should.not.exists(err); + should.exists(d); + d.should.have.property('id', 1); + d.should.have.property('name', 'checkCase'); + done(); + }); + }); + }); + it('should return an array of primary keys for strongloop.product', function(done) { db.discoverPrimaryKeys('product', {owner: 'strongloop'}, function(err, models) { if (err) { diff --git a/test/schema.sql b/test/schema.sql index ad6e1aaf..7020812c 100644 --- a/test/schema.sql +++ b/test/schema.sql @@ -113,7 +113,7 @@ ALTER SEQUENCE account_id_seq OWNED BY account.id; CREATE TABLE demo ( name text NOT NULL, - id integer NOT NULL + "demoId" integer NOT NULL ); @@ -133,7 +133,7 @@ CREATE SEQUENCE demo_id_seq -- Name: demo_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: strongloop -- -ALTER SEQUENCE demo_id_seq OWNED BY demo.id; +ALTER SEQUENCE demo_id_seq OWNED BY demo."demoId"; -- @@ -1243,7 +1243,7 @@ ALTER TABLE ONLY account -- ALTER TABLE ONLY demo - ADD CONSTRAINT demo_pkey PRIMARY KEY (id); + ADD CONSTRAINT demo_pkey PRIMARY KEY ("demoId"); -- From cf44d31dc1687853735a03517bb965fe2cef1148 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Fri, 6 Mar 2020 13:32:43 -0500 Subject: [PATCH 25/72] fix Signed-off-by: SAMI BETTAYEB --- test/postgresql.discover.test.js | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/test/postgresql.discover.test.js b/test/postgresql.discover.test.js index ae087a5c..729d434b 100644 --- a/test/postgresql.discover.test.js +++ b/test/postgresql.discover.test.js @@ -288,26 +288,25 @@ describe('Discover model primary keys', function() { }); }); - it('primary key should be discovered, and db generates instances properly', function(done) { + it('should discover primary key and db generates instances properly', function(done) { db.discoverPrimaryKeys('demo', function(err, models) { if (err) { console.error(err); done(err); } else { - models.forEach(function(m) { - assert.deepEqual(m, {owner: 'public', - tableName: 'demo', - columnName: 'demoId', - keySeq: 1, - pkName: 'demo_pkey'}); - }); + models.length.should.be.equal(1); + assert.deepEqual(models[0], {owner: 'public', + tableName: 'demo', + columnName: 'demoId', + keySeq: 1, + pkName: 'demo_pkey'}); } }); Demo.create({id: 1, name: 'checkCase'}, function(err) { - should.not.exists(err); + should.not.exist(err); Demo.findOne({}, function(err, d) { - should.not.exists(err); - should.exists(d); + should.not.exist(err); + should.exist(d); d.should.have.property('id', 1); d.should.have.property('name', 'checkCase'); done(); From 29cf613719678fd9d55ee82d2c1f49a68f39b00f Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Sun, 15 Mar 2020 19:27:11 -0400 Subject: [PATCH 26/72] fix README display on the site Signed-off-by: SAMI BETTAYEB --- README.md | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c733cf15..05f40a1f 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,12 @@ If you create a PostgreSQL data source using the data source generator as descri Use the [Data source generator](http://loopback.io/doc/en/lb3/Data-source-generator.html) to add a PostgreSQL data source to your application. The generator will prompt for the database server hostname, port, and other settings -required to connect to a PostgreSQL database. It will also run the `npm install` command above for you. +required to connect to a PostgreSQL database. It will also run the `npm install` command above for you. The entry in the application's `/server/datasources.json` will look like this: {% include code-caption.html content="/server/datasources.json" %} + ```javascript "mydb": { "name": "mydb", @@ -50,6 +51,7 @@ Edit `datasources.json` to add other properties that enable you to connect the You can also specify connection pool settings in `datasources.json`. For instance you can specify the minimum and the maximum pool size, and the maximum pool client's idle time before closing the client. Example of `datasource.json`: + ``` { "mypostgresdb": { @@ -68,6 +70,7 @@ Example of `datasource.json`: } } ``` + Check out [node-pg-pool](https://github.com/brianc/node-pg-pool) and [node postgres pooling example](https://github.com/brianc/node-postgres#pooling-example) for more information. ### Properties @@ -210,6 +213,7 @@ The model definition consists of the following properties. For example: {% include code-caption.html content="/common/models/model.json" %} + ```javascript { "name": "Inventory", @@ -404,10 +408,10 @@ You can query the nested fields with dot notation: ```javascript Customer.find({ where: { - 'address.state': 'California' + "address.state": "California" }, - order: 'address.city' -}) + order: "address.city" +}); ``` ## Discovery and auto-migration @@ -415,7 +419,7 @@ Customer.find({ ### Model discovery The PostgreSQL connector supports _model discovery_ that enables you to create LoopBack models -based on an existing database schema using the unified [database discovery API](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-discoverandbuildmodels). For more information on discovery, see [Discovering models from relational databases](https://loopback.io/doc/en/lb3/Discovering-models-from-relational-databases.html). +based on an existing database schema using the unified [database discovery API](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-discoverandbuildmodels). For more information on discovery, see [Discovering models from relational databases](https://loopback.io/doc/en/lb3/Discovering-models-from-relational-databases.html). ### Auto-migration @@ -429,8 +433,8 @@ model: a table, for example, PRODUCT under the 'public' schema within the databa The auto-migrate method: -* Defines a primary key for the properties whose `id` property is true (or a positive number). -* Creates a column with 'SERIAL' type if the `generated` property of the `id` property is true. +- Defines a primary key for the properties whose `id` property is true (or a positive number). +- Creates a column with 'SERIAL' type if the `generated` property of the `id` property is true. Destroying models may result in errors due to foreign key integrity. First delete any related models by calling delete on models with relationships. @@ -440,7 +444,7 @@ Foreign key constraints can be defined in the model `options`. Removing or updat If there is a reference to an object being deleted then the `DELETE` will fail. Likewise if there is a create with an invalid FK id then the `POST` will fail. -**Note**: The order of table creation is important. A referenced table must exist before creating a foreign key constraint. +**Note**: The order of table creation is important. A referenced table must exist before creating a foreign key constraint. For **LoopBack 4** users, define your models under the `models/` folder as follows: @@ -464,6 +468,7 @@ export class Customer extends Entity { name: string; } ``` + `order.model.ts`: ```ts @@ -494,7 +499,7 @@ export class Order extends Entity { For **LoopBack 3** users, you can define your model JSON schema as follows: ```json -{ +({ "name": "Customer", "options": { "idInjection": false @@ -512,7 +517,6 @@ For **LoopBack 3** users, you can define your model JSON schema as follows: } } }, - { "name": "Order", "options": { @@ -542,7 +546,7 @@ For **LoopBack 3** users, you can define your model JSON schema as follows: "length": 40 } } -} +}) ``` Auto-migrate supports the automatic generation of property values. For PostgreSQL, the default id type is _integer_. If you have `generated: true` in the id property, it generates integers by default: @@ -571,6 +575,7 @@ It is common to use UUIDs as the primary key in PostgreSQL instead of integers. }, } ``` + The setting uses `uuid-ossp` extension and `uuid_generate_v4()` function as default. If you'd like to use other extensions and functions, you can do: @@ -596,24 +601,35 @@ WARNING: It is the users' responsibility to make sure the provided extension and ## Running tests ### Own instance + If you have a local or remote PostgreSQL instance and would like to use that to run the test suite, use the following command: + - Linux + ```bash POSTGRESQL_HOST= POSTGRESQL_PORT= POSTGRESQL_USER= POSTGRESQL_PASSWORD= POSTGRESQL_DATABASE= CI=true npm test ``` + - Windows + ```bash SET POSTGRESQL_HOST= SET POSTGRESQL_PORT= SET POSTGRESQL_USER= SET POSTGRESQL_PASSWORD= SET POSTGRESQL_DATABASE= SET CI=true npm test ``` ### Docker + If you do not have a local PostgreSQL instance, you can also run the test suite with very minimal requirements. + - Assuming you have [Docker](https://docs.docker.com/engine/installation/) installed, run the following script which would spawn a PostgreSQL instance on your local: + ```bash source setup.sh ``` + where ``, ``, ``, `` and `` are optional parameters. The default values are `localhost`, `5432`, `root`, `pass` and `testdb` respectively. + - Run the test: + ```bash npm test ``` From d1313f67ab5b1f6ccb766c8ac1a52db9be70e342 Mon Sep 17 00:00:00 2001 From: Dominique Emond Date: Thu, 12 Mar 2020 15:17:00 -0400 Subject: [PATCH 27/72] Exclude 'deps' and '.github' from npm publish Signed-off-by: SAMI BETTAYEB --- package.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/package.json b/package.json index 7fd6c74f..23f6448a 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,13 @@ "lint": "eslint .", "posttest": "npm run lint" }, + "files": [ + "intl", + "lib", + "docs.json", + "index.js", + "setup.sh" + ], "dependencies": { "async": "^0.9.0", "bluebird": "^3.4.6", From ecf0c8139ce9b22d3bde689ef9d82450bf548a69 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Thu, 19 Mar 2020 11:58:30 -0400 Subject: [PATCH 28/72] fix readme layout Signed-off-by: SAMI BETTAYEB --- README.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 05f40a1f..fbdbbab1 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ Check out [node-pg-pool](https://github.com/brianc/node-pg-pool) and [node postg defaultIdSort Boolean/String Set to false to disable default sorting on id column(s). Set to numericIdOnly to only apply to IDs with a number type id. + @@ -313,11 +314,13 @@ See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for de ### LoopBack to PostgreSQL types - + - - + + + + + + + + @@ -531,6 +560,35 @@ CustomerRepository.find({ }); ``` +## Querying Postgres Array type fields + +**Note** The fields you are querying should be setup to use the postgresql array data type - see Defining models + +Assuming a model such as this: + +```ts + @property({ + type: ['string'], + postgresql: { + dataType: 'varchar[]', + }, + }) + categories?: string[]; +``` + +You can query the tags fields via setting allowExtendedOperators to true + +```ts +Model.dataSource.settings.allowExtendedOperators = true; + const post = await Post.find({where: { + { + categories: {'contains': ['AA']}, + } + } + }); +``` + + ## Discovery and auto-migration ### Model discovery diff --git a/lib/postgresql.js b/lib/postgresql.js index 0c5f9a05..8673e9f5 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -522,6 +522,9 @@ PostgreSQL.prototype.buildExpression = function(columnName, operator, const regexOperator = operatorValue.ignoreCase ? ' ~* ?' : ' ~ ?'; return new ParameterizedSQL(columnName + regexOperator, [operatorValue.source]); + case 'contains': + return new ParameterizedSQL(columnName + ' @> array[' + operatorValue.map((v) => `'${v}'`) + ']::' + + propertyDefinition.postgresql.dataType); default: // invoke the base implementation of `buildExpression` return this.invokeSuper('buildExpression', columnName, operator, diff --git a/test/postgresql.test.js b/test/postgresql.test.js index 08346f51..8e5a5606 100644 --- a/test/postgresql.test.js +++ b/test/postgresql.test.js @@ -263,6 +263,16 @@ describe('postgresql connector', function() { }); }); + it('should support where filter for array type field', async () => { + Post.dataSource.settings.allowExtendedOperators = true; + const post = await Post.find({where: {and: [ + { + categories: {'contains': ['AA']}, + }, + ]}}); + should.exist(post); + post.length.should.equal(1); + }); it('should support boolean types with false value', function(done) { Post.create( {title: 'T2', content: 'C2', approved: false, created: created}, From 21da7759d6c0b975958ea67dd81521271202a5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 6 Oct 2020 10:56:06 +0200 Subject: [PATCH 52/72] docs: improve README organization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- README.md | 93 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 80db2bc3..0aa11976 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ const config = {
For LoopBack 3 users -Use the [Data source generator](http://loopback.io/doc/en/lb3/Data-source-generator.html) to add a PostgreSQL data source to your application. +Use the [Data source generator](http://loopback.io/doc/en/lb3/Data-source-generator.html) to add a PostgreSQL data source to your application. The generator will prompt for the database server hostname, port, and other settings required to connect to a PostgreSQL database. It will also run the `npm install` command above for you. @@ -96,7 +96,7 @@ const config = { Check out [node-pg-pool](https://github.com/brianc/node-pg-pool) and [node postgres pooling example](https://github.com/brianc/node-postgres#pooling-example) for more information. -### Properties +### Configuration options
LoopBack TypePostgreSQL TypeLoopBack TypePostgreSQL Type
String
JSON
Text
Default
@@ -343,11 +346,13 @@ See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for de ### PostgreSQL types to LoopBack - + - - + + + + @@ -367,7 +372,7 @@ See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for de - TIME WITH TIME ZONETIME WITHOUT TIME ZONE + From 8afb67186aeb835f90a13ba340180b778a3c0fd1 Mon Sep 17 00:00:00 2001 From: Dominique Emond Date: Thu, 19 Mar 2020 15:00:07 -0400 Subject: [PATCH 29/72] 3.9.1 * fix readme layout (Agnes Lin) * fix README display on the site (Agnes Lin) * Exclude 'deps' and '.github' from npm publish (Dominique Emond) * fix (Agnes Lin) * tests: column should be discovered and mapped (Agnes Lin) * fix: `DEFAULT` for null values in where clause (DEEPAK RAJAMOHAN) * fix postgres random ci failure (Agnes Lin) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 18 ++++++++++++++++++ package.json | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index ac3959d9..0f6a6943 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,21 @@ +2020-03-19, Version 3.9.1 +========================= + + * fix readme layout (Agnes Lin) + + * fix README display on the site (Agnes Lin) + + * Exclude 'deps' and '.github' from npm publish (Dominique Emond) + + * fix (Agnes Lin) + + * tests: column should be discovered and mapped (Agnes Lin) + + * fix: `DEFAULT` for null values in where clause (DEEPAK RAJAMOHAN) + + * fix postgres random ci failure (Agnes Lin) + + 2020-02-25, Version 3.9.0 ========================= diff --git a/package.json b/package.json index 23f6448a..5ec04904 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "3.9.0", + "version": "3.9.1", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=8" From 769f49149bede05656af2475184de75b354922cf Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Thu, 19 Mar 2020 17:40:05 -0400 Subject: [PATCH 30/72] chore: update strong-globalize version Signed-off-by: SAMI BETTAYEB --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5ec04904..63e4c95b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "debug": "^4.1.1", "loopback-connector": "^4.10.2", "pg": "^7.0.0", - "strong-globalize": "^4.0.0", + "strong-globalize": "^5.0.5", "uuid": "^3.0.1" }, "devDependencies": { From 66d9438b6415e9d8a9e8c9e9e40b20d4271d2e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 17 Apr 2020 10:02:12 +0200 Subject: [PATCH 31/72] Drop support for Node.js 8.x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The version has reached end of life several months ago. Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- .travis.yml | 1 - package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cf895093..5cd68bd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: node_js node_js: - - "8" - "10" - "12" diff --git a/package.json b/package.json index 63e4c95b..464150aa 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "3.9.1", "description": "Loopback PostgreSQL Connector", "engines": { - "node": ">=8" + "node": ">=10" }, "keywords": [ "StrongLoop", From c449a3de2f75f4fbe4b72ca036f2dbb37c819c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 17 Apr 2020 10:02:46 +0200 Subject: [PATCH 32/72] Add Node.js 13.x to Travis CI matrix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5cd68bd8..582fb904 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: node_js node_js: - "10" - "12" + - "13" services: - postgresql From 2514d2907f14586c94a566e3d8c79adebac7ba20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 17 Apr 2020 10:14:03 +0200 Subject: [PATCH 33/72] Update dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - async to ^3.2 - chalk to ^4.0 - uuid to ^7.0 Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 464150aa..f2bfb4ee 100644 --- a/package.json +++ b/package.json @@ -27,14 +27,14 @@ "setup.sh" ], "dependencies": { - "async": "^0.9.0", + "async": "^3.2.0", "bluebird": "^3.4.6", - "chalk": "^3.0.0", + "chalk": "^4.0.0", "debug": "^4.1.1", "loopback-connector": "^4.10.2", "pg": "^7.0.0", - "strong-globalize": "^5.0.5", - "uuid": "^3.0.1" + "strong-globalize": "^6.0.0", + "uuid": "^7.0.3" }, "devDependencies": { "eslint": "^6.0.1", From 17c276b8a48ddeafc1f9e82edd5060153db8f9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 17 Apr 2020 10:15:09 +0200 Subject: [PATCH 34/72] [SEMVER-MAJOR] Upgrade `pg` to `8.0` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notable breaking changes: - Change default behavior when not specifying `rejectUnauthorized` with the SSL connection parameters. Previously we defaulted to `rejectUnauthorized: false` when it was not specifically included. We now default to `rejectUnauthorized: true`. Manually specify `{ ssl: { rejectUnauthorized: false } }` for old behavior. - Change default database when not specified to use the `user` config option if available. Previously `process.env.USER` was used. See pg's changelog for the full list of breaking changes. https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md#pg800 Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f2bfb4ee..04ea5ca0 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "chalk": "^4.0.0", "debug": "^4.1.1", "loopback-connector": "^4.10.2", - "pg": "^7.0.0", + "pg": "^8.0.2", "strong-globalize": "^6.0.0", "uuid": "^7.0.3" }, From a32a92a260f3a96e6668e7f7e99873c036c0b0c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 17 Apr 2020 10:19:34 +0200 Subject: [PATCH 35/72] Upgrade dev dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - mocha to ^7.1 - sinon to ^9.0 Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 04ea5ca0..804ce190 100644 --- a/package.json +++ b/package.json @@ -43,10 +43,10 @@ "juggler-v4": "file:./deps/juggler-v4", "lodash": "^4.17.4", "loopback-datasource-juggler": "^3.0.0 || ^4.0.0", - "mocha": "^6.1.4", + "mocha": "^7.1.1", "rc": "^1.0.0", "should": "^13.2.3", - "sinon": "^7.3.2" + "sinon": "^9.0.2" }, "repository": { "type": "git", From 72c4c27cc29cfda6e286d0f9094188c684c085cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 20 Apr 2020 14:22:48 +0200 Subject: [PATCH 36/72] README: add info about LTS policy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fbdbbab1..17697601 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,11 @@ [PostgreSQL](https://www.postgresql.org/), is a popular open-source object-relational database. The `loopback-connector-postgresql` module is the PostgreSQL connector for the LoopBack framework. -
For more information, see the documentation. +
+The PostgreSQL connector supports both LoopBack 3 and LoopBack 4. For more information, see +LoopBack 4 documentation, +LoopBack 3 documentation +and Module Long Term Support Policy below.

NOTE: The PostgreSQL connector requires PostgreSQL 8.x or 9.x.
@@ -603,6 +607,18 @@ If you'd like to use other extensions and functions, you can do: WARNING: It is the users' responsibility to make sure the provided extension and function are valid. +## Module Long Term Support Policy + +This module adopts the [Module Long Term Support (LTS)](http://github.com/CloudNativeJS/ModuleLTS) policy, with the following End Of Life (EOL) dates: + +| Version | Status | Published | EOL | +| ---------- | --------------- | --------- | -------------------- | +| 4.x | Current | Mar 2017 | Apr 2023 _(minimum)_ | +| 3.x | Active LTS | Mar 2017 | Apr 2022 | + +Learn more about our LTS plan in [docs](https://loopback.io/doc/en/contrib/Long-term-support.html). + + ## Running tests ### Own instance From d779f133c5719a2fc03c079629f2909191c05b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 21 Apr 2020 08:32:46 +0200 Subject: [PATCH 37/72] 5.0.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * README: add info about LTS policy (Miroslav Bajtoš) * Upgrade dev dependencies (Miroslav Bajtoš) * [SEMVER-MAJOR] Upgrade `pg` to `8.0` (Miroslav Bajtoš) * Update dependencies (Miroslav Bajtoš) * Add Node.js 13.x to Travis CI matrix (Miroslav Bajtoš) * Drop support for Node.js 8.x (Miroslav Bajtoš) * chore: update strong-globalize version (Diana Lau) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 34 ++++++++++++++++++++++++++++++++++ README.md | 2 +- package.json | 2 +- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0f6a6943..5a048b75 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,37 @@ +2020-04-21, Version 5.0.0 +========================= + + * README: add info about LTS policy (Miroslav Bajtoš) + + * Upgrade dev dependencies (Miroslav Bajtoš) + + * [SEMVER-MAJOR] Upgrade `pg` to `8.0` (Miroslav Bajtoš) + + * Update dependencies (Miroslav Bajtoš) + + * Add Node.js 13.x to Travis CI matrix (Miroslav Bajtoš) + + * Drop support for Node.js 8.x (Miroslav Bajtoš) + + * chore: update strong-globalize version (Diana Lau) + +## Breaking changes + +The client library `pg` was upgraded to `8.0` with the following notable changes: + +- Change default behavior when not specifying `rejectUnauthorized` with the + SSL connection parameters. Previously we defaulted to + `rejectUnauthorized: false` when it was not specifically included. We now + default to `rejectUnauthorized: true`. Manually specify + `{ ssl: { rejectUnauthorized: false } }` for old behavior. + +- Change default database when not specified to use the `user` config option + if available. Previously `process.env.USER` was used. + +See pg's changelog for the full list of breaking changes. +https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md#pg800 + + 2020-03-19, Version 3.9.1 ========================= diff --git a/README.md b/README.md index 17697601..1a481f49 100644 --- a/README.md +++ b/README.md @@ -613,7 +613,7 @@ This module adopts the [Module Long Term Support (LTS)](http://github.com/CloudN | Version | Status | Published | EOL | | ---------- | --------------- | --------- | -------------------- | -| 4.x | Current | Mar 2017 | Apr 2023 _(minimum)_ | +| 5.x | Current | Apr 2020 | Apr 2023 _(minimum)_ | | 3.x | Active LTS | Mar 2017 | Apr 2022 | Learn more about our LTS plan in [docs](https://loopback.io/doc/en/contrib/Long-term-support.html). diff --git a/package.json b/package.json index 804ce190..420aa850 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "3.9.1", + "version": "5.0.0", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=10" From 007cdfaaedcf1564604256b058d7af67c6a9dff0 Mon Sep 17 00:00:00 2001 From: Selim Arsever Date: Tue, 5 May 2020 22:36:27 +0200 Subject: [PATCH 38/72] Fix serialization of arrays of string in update (#428) Signed-off-by: SAMI BETTAYEB --- lib/postgresql.js | 18 ++++++++++++ test/postgresql.test.js | 62 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/lib/postgresql.js b/lib/postgresql.js index b4c62baf..0c5f9a05 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -766,6 +766,24 @@ PostgreSQL.prototype.toColumnValue = function(prop, val, isWhereClause) { }); } + if (Array.isArray(prop.type)) { + // There is two possible cases for the type of "val" as well as two cases for dataType + const isArrayDataType = prop.postgresql && prop.postgresql.dataType === 'varchar[]'; + if (Array.isArray(val)) { + if (isArrayDataType) { + return val; + } else { + return JSON.stringify(val); + } + } else { + if (isArrayDataType) { + return JSON.parse(val); + } else { + return val; + } + } + } + return val; }; diff --git a/test/postgresql.test.js b/test/postgresql.test.js index 83c80b28..08346f51 100644 --- a/test/postgresql.test.js +++ b/test/postgresql.test.js @@ -64,6 +64,15 @@ describe('postgresql connector', function() { loc: 'GeoPoint', created: Date, approved: Boolean, + tags: { + type: ['string'], + }, + categories: { + type: ['string'], + postgresql: { + dataType: 'varchar[]', + }, + }, }); created = new Date(); }); @@ -201,6 +210,59 @@ describe('postgresql connector', function() { }); }); + it('should support creating and updating arrays with default dataType', function(done) { + let postId; + Post.create({title: 'Updating Arrays', content: 'Content', tags: ['AA', 'AB']}) + .then((post)=> { + postId = post.id; + post.should.have.property('tags'); + post.tags.should.be.Array(); + post.tags.length.should.eql(2); + post.tags.should.eql(['AA', 'AB']); + return Post.updateAll({where: {id: postId}}, {tags: ['AA', 'AC']}); + }) + .then(()=> { + return Post.findOne({where: {id: postId}}); + }) + .then((post)=> { + post.should.have.property('tags'); + post.tags.should.be.Array(); + post.tags.length.should.eql(2); + post.tags.should.eql(['AA', 'AC']); + done(); + }) + .catch((error) => { + done(error); + }); + }); + + it('should support creating and updating arrays with "varchar[]" dataType', function(done) { + let postId; + Post.create({title: 'Updating Arrays', content: 'Content', categories: ['AA', 'AB']}) + .then((post)=> { + postId = post.id; + post.should.have.property('categories'); + post.should.have.property('categories'); + post.categories.should.be.Array(); + post.categories.length.should.eql(2); + post.categories.should.eql(['AA', 'AB']); + return Post.updateAll({where: {id: postId}}, {categories: ['AA', 'AC']}); + }) + .then(()=> { + return Post.findOne({where: {id: postId}}); + }) + .then((post)=> { + post.should.have.property('categories'); + post.categories.should.be.Array(); + post.categories.length.should.eql(2); + post.categories.should.eql(['AA', 'AC']); + done(); + }) + .catch((error) => { + done(error); + }); + }); + it('should support boolean types with false value', function(done) { Post.create( {title: 'T2', content: 'C2', approved: false, created: created}, From 1c4d97dd547edcb86f70a19860e6706ff20a5e0b Mon Sep 17 00:00:00 2001 From: jannyHou Date: Wed, 6 May 2020 16:33:55 -0400 Subject: [PATCH 39/72] 5.0.1 * Fix serialization of arrays of string in update (#428) (Selim Arsever) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 22 ++++++---------------- package.json | 2 +- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5a048b75..47de7da4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +2020-05-06, Version 5.0.1 +========================= + + * Fix serialization of arrays of string in update (#428) (Selim Arsever) + + 2020-04-21, Version 5.0.0 ========================= @@ -15,22 +21,6 @@ * chore: update strong-globalize version (Diana Lau) -## Breaking changes - -The client library `pg` was upgraded to `8.0` with the following notable changes: - -- Change default behavior when not specifying `rejectUnauthorized` with the - SSL connection parameters. Previously we defaulted to - `rejectUnauthorized: false` when it was not specifically included. We now - default to `rejectUnauthorized: true`. Manually specify - `{ ssl: { rejectUnauthorized: false } }` for old behavior. - -- Change default database when not specified to use the `user` config option - if available. Previously `process.env.USER` was used. - -See pg's changelog for the full list of breaking changes. -https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md#pg800 - 2020-03-19, Version 3.9.1 ========================= diff --git a/package.json b/package.json index 420aa850..cb08e306 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "5.0.0", + "version": "5.0.1", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=10" From d647d79d7f0a7a86d5daa144cc45537ee19674bc Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Fri, 22 May 2020 16:22:53 -0400 Subject: [PATCH 40/72] docs: update readme with more lb4 form Signed-off-by: SAMI BETTAYEB --- README.md | 351 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 259 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index 1a481f49..6c91ac4e 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,32 @@ In your application root directory, enter this command to install the connector: $ npm install loopback-connector-postgresql --save ``` -This installs the module from npm and adds it as a dependency to the application's `package.json` file. +This installs the module from npm and adds it as a dependency to the application's `package.json` file. If you create a PostgreSQL data source using the data source generator as described below, you don't have to do this, since the generator will run `npm install` for you. ## Creating a data source -Use the [Data source generator](http://loopback.io/doc/en/lb3/Data-source-generator.html) to add a PostgreSQL data source to your application. +For LoopBack 4 users, use the LoopBack 4 [Command-line interface](https://loopback.io/doc/en/lb4/Command-line-interface.html) to generate a DataSource with PostgreSQL connector to your LB4 application. Run [`lb4 datasource`](https://loopback.io/doc/en/lb4/DataSource-generator.html), it will prompt for configurations such as host, post, etc. that are required to connect to a PostgreSQL database. + +After setting it up, the configuration can be found under `src/datasources/.datasource.ts`, which would look like this: + +```ts +const config = { + name: 'db', + connector: 'postgresql', + url: '', + host:'localhost', + port: 5432, + user: 'user', + password: 'pass', + database: 'testdb', +}; +``` + +
For LoopBack 3 users + +Use the [Data source generator](http://loopback.io/doc/en/lb3/Data-source-generator.html) to add a PostgreSQL data source to your application. The generator will prompt for the database server hostname, port, and other settings required to connect to a PostgreSQL database. It will also run the `npm install` command above for you. @@ -48,31 +67,31 @@ The entry in the application's `/server/datasources.json` will look like this: } ``` -Edit `datasources.json` to add other properties that enable you to connect the data source to a PostgreSQL database. +Edit `datasources.json` to add other properties that enable you to connect the data source to a PostgreSQL database. + +
### Connection Pool Settings -You can also specify connection pool settings in `datasources.json`. For instance you can specify the minimum and the maximum pool size, and the maximum pool client's idle time before closing the client. +You can also specify connection pool settings in `.datasource.ts` ( or `datasources.json` for LB3 users). For instance you can specify the minimum and the maximum pool size, and the maximum pool client's idle time before closing the client. -Example of `datasource.json`: +Example of `db.datasource.ts`: -``` -{ - "mypostgresdb": { - "host": "mydbhost", - "port": 5432, - "url": "postgres://admin:password1@mydbhost:5432/db1?ssl=false", - "database": "db1", - "password": "password1", - "name": "mypostgresdb", - "user": "admin", - "connector": "postgresql", - "min": 5, - "max": 200, - "idleTimeoutMillis": 60000, - "ssl": false - } -} +```ts +const config = { + name: 'db', + connector: 'postgresql', + url: '', + host: 'localhost', + port: 5432, + user: 'user', + password: 'pass', + database: 'testdb', + min: 5, + max: 200, + idleTimeoutMillis: 60000, + ssl: false +}; ``` Check out [node-pg-pool](https://github.com/brianc/node-pg-pool) and [node postgres pooling example](https://github.com/brianc/node-postgres#pooling-example) for more information. @@ -169,22 +188,79 @@ information about configuration parameters, see [node-postgres documentation](ht A common PostgreSQL configuration is to connect to the UNIX domain socket `/var/run/postgresql/.s.PGSQL.5432` instead of using the TCP/IP port. For example: -```javascript -{ - "postgres": { - "host": "/var/run/postgresql/", - "port": "5432", - "database": "dbname", - "username": "dbuser", - "password": "dbpassword", - "name": "postgres", - "debug": true, - "connector": "postgresql" +```ts +const config = { + name: 'db', + connector: 'postgresql', + url: '', + host: '/var/run/postgresql/', + port: 5432, + user: 'user', + password: 'pass', + database: 'testdb', + debug: true +}; +``` + +## Defining models + +LoopBack allows you to specify some database settings through the model definition and/or the property definition. These definitions would be mapped to the database. Please check out the CLI [`lb4 model`](https://loopback.io/doc/en/lb4/Model-generator.html) for generating LB4 models. The following is a typical LoopBack 4 model that specifies the schema, table and column details through model definition and property definitions: + +```ts +@model({ + settings: { postgresql: { schema: 'public', table: 'inventory'} }, +}) +export class Inventory extends Entity { + @property({ + type: 'number', + required: true, + scale: 0, + id: 1, + postgresql: { + columnName: 'id', + dataType: 'integer', + dataLength: null, + dataPrecision: null, + dataScale: 0, + nullable: 'NO', + }, + }) + id: number; + + @property({ + type: 'string', + postgresql: { + columnName: 'name', + dataType: 'text', + dataLength: null, + dataPrecision: null, + dataScale: null, + nullable: 'YES', + }, + }) + name?: string; + + @property({ + type: 'boolean', + required: true, + postgresql: { + columnName: 'available', + dataType: 'boolean', + dataLength: null, + dataPrecision: null, + dataScale: null, + nullable: 'NO', + }, + }) + available: boolean; + + constructor(data?: Partial) { + super(data); } } ``` -## Defining models +
For LoopBack 3 users The model definition consists of the following properties. @@ -311,9 +387,13 @@ For example: } ``` +
+ +To learn more about specifying database settings, please check the section [Data Mapping Properties](https://loopback.io/doc/en/lb4/Model.html#data-mapping-properties). + ## Type mapping -See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for details on LoopBack's data types. +See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for details on LoopBack's data types. ### LoopBack to PostgreSQL types @@ -347,6 +427,37 @@ See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for de
PostgreSQL TypeLoopBack TypePostgreSQL TypeLoopBack Type
BOOLEAN BooleanNumber
DATE
TIMESTAMP
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITHOUT TIME ZONE
TIME
DATE
TIMESTAMP
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITHOUT TIME ZONE
TIME
TIME WITH TIME ZONE
TIME WITHOUT TIME ZONE
Date
+Besides the basic LoopBack types, as we introduced above, you can also specify the database type for model properties. It would be mapped to the database (see [Data Mapping Properties](https://loopback.io/doc/en/lb4/Model.html#data-mapping-properties)). For example, we would like the property `price` to have database type `double precision` in the corresponding table in the database, we have specify it as following: + +```ts + @property({ + type: 'number', + postgresql: { + dataType: 'double precision', + }, + }) + price?: number; +``` + +
For LoopBack 3 users + +```javascript +"properties": { + // .. + "price": { + "type": "Number", + "postgresql": { + "dataType": "double precision", + } + }, +``` + +
+ +{% include warning.html content=" +Not all database types are supported for operating CRUD operations and queries with filters. For example, type Array cannot be filtered correctly, see GitHub issues: [# 441](https://github.com/strongloop/loopback-connector-postgresql/issues/441) and [# 342](https://github.com/strongloop/loopback-connector-postgresql/issues/342). +" %} + ### PostgreSQL types to LoopBack @@ -372,7 +483,7 @@ See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for de - + @@ -398,28 +509,24 @@ For details, see the corresponding [driver issue](https://github.com/brianc/node Assuming a model such as this: -```json -{ - "name": "Customer", - "properties": { - "address": { - "type": "object", - "postgresql": { - "dataType": "json" - } - } - } -} +```ts + @property({ + type: 'number', + postgresql: { + dataType: 'double precision', + }, + }) + price?: number; ``` You can query the nested fields with dot notation: -```javascript -Customer.find({ +```ts +CustomerRepository.find({ where: { - "address.state": "California" + address.state: 'California', }, - order: "address.city" + order: 'address.city', }); ``` @@ -428,34 +535,87 @@ Customer.find({ ### Model discovery The PostgreSQL connector supports _model discovery_ that enables you to create LoopBack models -based on an existing database schema using the unified [database discovery API](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-discoverandbuildmodels). For more information on discovery, see [Discovering models from relational databases](https://loopback.io/doc/en/lb3/Discovering-models-from-relational-databases.html). +based on an existing database schema. Once you defined your datasource: +- LoopBack 4 users could use the commend [`lb4 discover`](https://loopback.io/doc/en/lb4/Discovering-models.html) to discover models. +- For LB3 users, please check [Discovering models from relational databases](https://loopback.io/doc/en/lb3/Discovering-models-from-relational-databases.html). + +(See [database discovery API](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-discoverandbuildmodels) for related APIs information) ### Auto-migration The PostgreSQL connector also supports _auto-migration_ that enables you to create a database schema -from LoopBack models using the [LoopBack automigrate method](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-automigrate). +from LoopBack models. -For more information on auto-migration, see [Creating a database schema from models](https://loopback.io/doc/en/lb3/Creating-a-database-schema-from-models.html) for more information. +For example, based on the following model, the auto-migration method would create/alter existing `customer` table under `public` schema in the database. Table `customer` would have two columns: `name` and `id`, where `id` is also the primary key and has the default value `SERIAL` as it has definition of `type: 'Number'` and `generated: true`: -LoopBack PostgreSQL connector creates the following schema objects for a given -model: a table, for example, PRODUCT under the 'public' schema within the database. +```ts +@model() +export class Customer extends Entity { + @property({ + id: true, + type: 'Number', + required: false + }) + id: number; -The auto-migrate method: + @property({ + type: 'string' + }) + name: string; +} +``` -- Defines a primary key for the properties whose `id` property is true (or a positive number). -- Creates a column with 'SERIAL' type if the `generated` property of the `id` property is true. +By default, tables generated by the auto-migration are under `public` schema and named in lowercase. -Destroying models may result in errors due to foreign key integrity. First delete any related models by calling delete on models with relationships. +Besides the basic model metadata, LoopBack allows you to specify part of the database schema definition via the +property definition, which would be mapped to the database. -### Auto-migrate/Auto-update models with foreign keys +For example, based on the following model, after running the auto-migration script, a table named `CUSTOMER` under schema `market` will be created. Moreover, you can also have different names for your property and the corresponding column. In the example, by specifying the column name, the property `name` will be mapped to the `customer_name` column. This is useful when your database has a different naming convention than LoopBack (camelCase). -Foreign key constraints can be defined in the model `options`. Removing or updating the value of `foreignKeys` will be updated or delete or update the constraints in the db tables. +```ts +@model( + settings: { + postgresql: {schema: 'market', table: 'CUSTOMER'}, + } +) +export class Customer extends Entity { + @property({ + id: true, + type: 'Number', + required: false + }) + id: number; + + @property({ + type: 'string', + postgresql: { + columnName: 'customer_name' + } + }) + name: string; +} +``` + +For how to run the script and more details: +- For LB4 users, please check [Database Migration](https://loopback.io/doc/en/lb4/Database-migrations.html) +- For LB3 users, please check [Creating a database schema from models](https://loopback.io/doc/en/lb3/Creating-a-database-schema-from-models.html) + +(See [LoopBack auto-migrate method](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-automigrate) for related APIs information) + +Here are some limitations and tips: + +- If you defined `generated: true` in the id property, it generates integers by default. For auto-generated uuid, see [Auto-generated id property](#auto-generated-id-property) +- Only the id property supports the auto-generation setting `generated: true` for now +- Auto-migration doesn't create foreign key constraints by default. But they can be defined through the model definition. See [Auto-migrate with foreign keys](#auto-migrateauto-update-models-with-foreign-keys) +- Destroying models may result in errors due to foreign key integrity. First delete any related models by calling delete on models with relationships. + +### Auto-migrate/Auto-update models with foreign keys -If there is a reference to an object being deleted then the `DELETE` will fail. Likewise if there is a create with an invalid FK id then the `POST` will fail. +Foreign key constraints can be defined in the model definition. **Note**: The order of table creation is important. A referenced table must exist before creating a foreign key constraint. -For **LoopBack 4** users, define your models under the `models/` folder as follows: +Define your models and the foreign key constraints as follows: `customer.model.ts`: @@ -465,14 +625,12 @@ export class Customer extends Entity { @property({ id: true, type: 'Number', - required: false, - length: 20 + required: false }) id: number; @property({ - type: 'string', - length: 20 + type: 'string' }) name: string; } @@ -481,31 +639,38 @@ export class Customer extends Entity { `order.model.ts`: ```ts -@model() +@model({ + settings: { + foreignKeys: { + fk_order_customerId: { + name: 'fk_order_customerId', + entity: 'Customer', + entityKey: 'id', + foreignKey: 'customerId', + }, + }, + }) export class Order extends Entity { @property({ id: true, type: 'Number', - required: false, - length: 20 + required: false }) id: number; @property({ - type: 'string', - length: 20 + type: 'string' }) name: string; @property({ - type: 'Number', - length: 20 + type: 'Number' }) customerId: number; } ``` -For **LoopBack 3** users, you can define your model JSON schema as follows: +
For LoopBack 3 users ```json ({ @@ -516,13 +681,11 @@ For **LoopBack 3** users, you can define your model JSON schema as follows: "properties": { "id": { "type": "Number", - "length": 20, "id": 1 }, "name": { "type": "String", - "required": false, - "length": 40 + "required": false } } }, @@ -541,24 +704,29 @@ For **LoopBack 3** users, you can define your model JSON schema as follows: }, "properties": { "id": { - "type": "Number", - "length": 20, + "type": "Number" "id": 1 }, "customerId": { - "type": "Number", - "length": 20 + "type": "Number" }, "description": { "type": "String", - "required": false, - "length": 40 + "required": false } } }) ``` -Auto-migrate supports the automatic generation of property values. For PostgreSQL, the default id type is _integer_. If you have `generated: true` in the id property, it generates integers by default: +
+
+{% include tips.html content=" +Removing or updating the value of `foreignKeys` will be updated or delete or update the constraints in the db tables. If there is a reference to an object being deleted then the `DELETE` will fail. Likewise if there is a create with an invalid FK id then the `POST` will fail. +" %} + +### Auto-generated id property + +Auto-migrate supports the automatic generation of property values for the id property. For PostgreSQL, the default id type is _integer_. Thus if you have `generated: true` in the id property, it generates integers by default: ```ts { @@ -611,14 +779,13 @@ WARNING: It is the users' responsibility to make sure the provided extension and This module adopts the [Module Long Term Support (LTS)](http://github.com/CloudNativeJS/ModuleLTS) policy, with the following End Of Life (EOL) dates: -| Version | Status | Published | EOL | -| ---------- | --------------- | --------- | -------------------- | -| 5.x | Current | Apr 2020 | Apr 2023 _(minimum)_ | -| 3.x | Active LTS | Mar 2017 | Apr 2022 | +| Version | Status | Published | EOL | +| ------- | ---------- | --------- | -------------------- | +| 5.x | Current | Apr 2020 | Apr 2023 _(minimum)_ | +| 3.x | Active LTS | Mar 2017 | Apr 2022 | Learn more about our LTS plan in [docs](https://loopback.io/doc/en/contrib/Long-term-support.html). - ## Running tests ### Own instance From d92845f4c238d10945f5925f41d44cec6302ccb4 Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Thu, 28 May 2020 14:41:10 -0400 Subject: [PATCH 41/72] fix: use tip.html Signed-off-by: SAMI BETTAYEB --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c91ac4e..d663e156 100644 --- a/README.md +++ b/README.md @@ -720,7 +720,7 @@ export class Order extends Entity {
-{% include tips.html content=" +{% include tip.html content=" Removing or updating the value of `foreignKeys` will be updated or delete or update the constraints in the db tables. If there is a reference to an object being deleted then the `DELETE` will fail. Likewise if there is a create with an invalid FK id then the `POST` will fail. " %} From d5d5ea26c0fc4ffe779ab9e78438b5d83a1be734 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Thu, 4 Jun 2020 13:50:03 -0400 Subject: [PATCH 42/72] fix: fix example prop def Signed-off-by: SAMI BETTAYEB --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d663e156..b2f57386 100644 --- a/README.md +++ b/README.md @@ -392,7 +392,7 @@ For example: To learn more about specifying database settings, please check the section [Data Mapping Properties](https://loopback.io/doc/en/lb4/Model.html#data-mapping-properties). ## Type mapping - + See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for details on LoopBack's data types. ### LoopBack to PostgreSQL types @@ -554,7 +554,7 @@ export class Customer extends Entity { @property({ id: true, type: 'Number', - required: false + generated: true }) id: number; @@ -582,7 +582,7 @@ export class Customer extends Entity { @property({ id: true, type: 'Number', - required: false + generated: true }) id: number; @@ -625,7 +625,7 @@ export class Customer extends Entity { @property({ id: true, type: 'Number', - required: false + generated: true }) id: number; @@ -654,7 +654,7 @@ export class Order extends Entity { @property({ id: true, type: 'Number', - required: false + generated: true }) id: number; From da5598af8671928a9b14a2093253d80e2cdcbfd0 Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Fri, 5 Jun 2020 18:28:03 -0400 Subject: [PATCH 43/72] fix: fix uuid setup Signed-off-by: SAMI BETTAYEB --- README.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b2f57386..efa08b2c 100644 --- a/README.md +++ b/README.md @@ -724,7 +724,7 @@ export class Order extends Entity { Removing or updating the value of `foreignKeys` will be updated or delete or update the constraints in the db tables. If there is a reference to an object being deleted then the `DELETE` will fail. Likewise if there is a create with an invalid FK id then the `POST` will fail. " %} -### Auto-generated id property +### Auto-generated ids Auto-migrate supports the automatic generation of property values for the id property. For PostgreSQL, the default id type is _integer_. Thus if you have `generated: true` in the id property, it generates integers by default: @@ -737,10 +737,25 @@ Auto-migrate supports the automatic generation of property values for the id pro } ``` -It is common to use UUIDs as the primary key in PostgreSQL instead of integers. You can enable it with the following settings: +It is common to use UUIDs as the primary key in PostgreSQL instead of integers. You can enable it with either the following ways: + +- use uuid that is **generated by your LB application** by setting [`defaultFn: uuid`](https://loopback.io/doc/en/lb4/Model.html#property-decorator): + ```ts -{ + @property({ + id: true, + type: 'string' + defaultFn: 'uuid', + // generated: true, -> not needed + }) + id: string; +``` + +- use PostgreSQL built-in (extension and) uuid functions: + +```ts + @property({ id: true, type: 'String', required: false, @@ -750,7 +765,8 @@ It is common to use UUIDs as the primary key in PostgreSQL instead of integers. postgresql: { dataType: 'uuid', }, -} +}) + id: string; ``` The setting uses `uuid-ossp` extension and `uuid_generate_v4()` function as default. @@ -758,7 +774,7 @@ The setting uses `uuid-ossp` extension and `uuid_generate_v4()` function as defa If you'd like to use other extensions and functions, you can do: ```ts -{ + @property({ id: true, type: 'String', required: false, @@ -770,7 +786,8 @@ If you'd like to use other extensions and functions, you can do: extension: 'myExtension', defaultFn: 'myuuid' }, -} +}) + id: string; ``` WARNING: It is the users' responsibility to make sure the provided extension and function are valid. From 6f95976cce16996eb95e1edeb742a3f16e384fd8 Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Fri, 10 Jul 2020 16:21:32 -0400 Subject: [PATCH 44/72] 5.0.2 * fix: fix uuid setup (Agnes Lin) * fix: fix example prop def (Agnes Lin) * fix: use tip.html (Diana Lau) * docs: update readme with more lb4 form (Agnes Lin) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 47de7da4..0a74108d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,15 @@ +2020-07-10, Version 5.0.2 +========================= + + * fix: fix uuid setup (Agnes Lin) + + * fix: fix example prop def (Agnes Lin) + + * fix: use tip.html (Diana Lau) + + * docs: update readme with more lb4 form (Agnes Lin) + + 2020-05-06, Version 5.0.1 ========================= diff --git a/package.json b/package.json index cb08e306..675695e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "5.0.1", + "version": "5.0.2", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=10" From e30bd72e9f4bcb89128ecb3515132f91070f1b88 Mon Sep 17 00:00:00 2001 From: karanssj4 Date: Wed, 24 Jun 2020 01:01:13 +0530 Subject: [PATCH 45/72] Update .travis.yml Signed-off-by: SAMI BETTAYEB --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 582fb904..2f34419a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ node_js: - "10" - "12" - "13" + - "14" services: - postgresql From 172c75b9c6f7fd16e539407ab4fd2c1ac8ce042b Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Thu, 13 Aug 2020 16:27:35 -0400 Subject: [PATCH 46/72] docs: update loopback types link Signed-off-by: SAMI BETTAYEB --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index efa08b2c..52456ef2 100644 --- a/README.md +++ b/README.md @@ -392,8 +392,9 @@ For example: To learn more about specifying database settings, please check the section [Data Mapping Properties](https://loopback.io/doc/en/lb4/Model.html#data-mapping-properties). ## Type mapping - -See [LoopBack types](http://loopback.io/doc/en/lb3/LoopBack-types.html) for details on LoopBack's data types. + +See [LoopBack 4 types](http://loopback.io/doc/en/lb4/LoopBack-types.html) (or [LoopBack 3 types](http://loopback.io/doc/en/lb3/LoopBack-types.html)) for +details on LoopBack's data types. ### LoopBack to PostgreSQL types From 46eafe48ebb08eb87242349d2d66ff484da3af72 Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Thu, 20 Aug 2020 21:26:25 -0400 Subject: [PATCH 47/72] chore: switch to DCO Signed-off-by: Diana Lau Signed-off-by: SAMI BETTAYEB --- .github/PULL_REQUEST_TEMPLATE.md | 3 +- CONTRIBUTING.md | 130 ++----------------------------- 2 files changed, 8 insertions(+), 125 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3547aefd..2cdc707a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,8 +10,7 @@ See also #23 ## Checklist -👉 [Read and sign the CLA (Contributor License Agreement)](https://cla.strongloop.com/agreements/strongloop/loopback-connector-postgresql) 👈 - +- [ ] DCO (Developer Certificate of Origin) [signed in all commits](https://loopback.io/doc/en/contrib/code-contrib.html) - [ ] `npm test` passes on your machine - [ ] New tests added or existing tests modified to cover all changes - [ ] Code conforms with the [style guide](https://loopback.io/doc/en/contrib/style-guide-es6.html) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1344af91..dbc10d03 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,132 +19,16 @@ Contributing to `loopback-connector-postgresql` is easy. In a few simple steps: * Submit a pull request through Github. -### Contributor License Agreement ### +### Developer Certificate of Origin -``` - Individual Contributor License Agreement - - By signing this Individual Contributor License Agreement - ("Agreement"), and making a Contribution (as defined below) to - StrongLoop, Inc. ("StrongLoop"), You (as defined below) accept and - agree to the following terms and conditions for Your present and - future Contributions submitted to StrongLoop. Except for the license - granted in this Agreement to StrongLoop and recipients of software - distributed by StrongLoop, You reserve all right, title, and interest - in and to Your Contributions. - - 1. Definitions - - "You" or "Your" shall mean the copyright owner or the individual - authorized by the copyright owner that is entering into this - Agreement with StrongLoop. - - "Contribution" shall mean any original work of authorship, - including any modifications or additions to an existing work, that - is intentionally submitted by You to StrongLoop for inclusion in, - or documentation of, any of the products owned or managed by - StrongLoop ("Work"). For purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication - sent to StrongLoop or its representatives, including but not - limited to communication or electronic mailing lists, source code - control systems, and issue tracking systems that are managed by, - or on behalf of, StrongLoop for the purpose of discussing and - improving the Work, but excluding communication that is - conspicuously marked or otherwise designated in writing by You as - "Not a Contribution." - - 2. You Grant a Copyright License to StrongLoop - - Subject to the terms and conditions of this Agreement, You hereby - grant to StrongLoop and recipients of software distributed by - StrongLoop, a perpetual, worldwide, non-exclusive, no-charge, - royalty-free, irrevocable copyright license to reproduce, prepare - derivative works of, publicly display, publicly perform, - sublicense, and distribute Your Contributions and such derivative - works under any license and without any restrictions. - - 3. You Grant a Patent License to StrongLoop - - Subject to the terms and conditions of this Agreement, You hereby - grant to StrongLoop and to recipients of software distributed by - StrongLoop a perpetual, worldwide, non-exclusive, no-charge, - royalty-free, irrevocable (except as stated in this Section) - patent license to make, have made, use, offer to sell, sell, - import, and otherwise transfer the Work under any license and - without any restrictions. The patent license You grant to - StrongLoop under this Section applies only to those patent claims - licensable by You that are necessarily infringed by Your - Contributions(s) alone or by combination of Your Contributions(s) - with the Work to which such Contribution(s) was submitted. If any - entity institutes a patent litigation against You or any other - entity (including a cross-claim or counterclaim in a lawsuit) - alleging that Your Contribution, or the Work to which You have - contributed, constitutes direct or contributory patent - infringement, any patent licenses granted to that entity under - this Agreement for that Contribution or Work shall terminate as - of the date such litigation is filed. - - 4. You Have the Right to Grant Licenses to StrongLoop - - You represent that You are legally entitled to grant the licenses - in this Agreement. - - If Your employer(s) has rights to intellectual property that You - create, You represent that You have received permission to make - the Contributions on behalf of that employer, that Your employer - has waived such rights for Your Contributions, or that Your - employer has executed a separate Corporate Contributor License - Agreement with StrongLoop. +This project uses [DCO](https://developercertificate.org/). Be sure to sign off +your commits using the `-s` flag or adding `Signed-off-By: Name` in the +commit message. - 5. The Contributions Are Your Original Work +**Example** - You represent that each of Your Contributions are Your original - works of authorship (see Section 8 (Submissions on Behalf of - Others) for submission on behalf of others). You represent that to - Your knowledge, no other person claims, or has the right to claim, - any right in any intellectual property right related to Your - Contributions. - - You also represent that You are not legally obligated, whether by - entering into an agreement or otherwise, in any way that conflicts - with the terms of this Agreement. - - You represent that Your Contribution submissions include complete - details of any third-party license or other restriction (including, - but not limited to, related patents and trademarks) of which You - are personally aware and which are associated with any part of - Your Contributions. - - 6. You Don't Have an Obligation to Provide Support for Your Contributions - - You are not expected to provide support for Your Contributions, - except to the extent You desire to provide support. You may provide - support for free, for a fee, or not at all. - - 6. No Warranties or Conditions - - StrongLoop acknowledges that unless required by applicable law or - agreed to in writing, You provide Your Contributions on an "AS IS" - BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER - EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES - OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR - FITNESS FOR A PARTICULAR PURPOSE. - - 7. Submission on Behalf of Others - - If You wish to submit work that is not Your original creation, You - may submit it to StrongLoop separately from any Contribution, - identifying the complete details of its source and of any license - or other restriction (including, but not limited to, related - patents, trademarks, and license agreements) of which You are - personally aware, and conspicuously marking the work as - "Submitted on Behalf of a Third-Party: [named here]". - - 8. Agree to Notify of Change of Circumstances - - You agree to notify StrongLoop of any facts or circumstances of - which You become aware that would make these representations - inaccurate in any respect. Email us at callback@strongloop.com. +``` +git commit -s -m "feat: my commit message" ``` [Google C++ Style Guide]: https://google.github.io/styleguide/cppguide.html From c1f045745ef884196f03421be7c603fff62504f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 28 Aug 2020 09:01:04 +0200 Subject: [PATCH 48/72] fix setup script to not exit calling shell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace `exit 1` to `return 1`, otherwise the entire shell (terminal tab) is closed on errors. Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- setup.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.sh b/setup.sh index 65ac423c..f06d1a28 100755 --- a/setup.sh +++ b/setup.sh @@ -38,7 +38,7 @@ docker -v > /dev/null 2>&1 DOCKER_EXISTS=$? if [ "$DOCKER_EXISTS" -ne 0 ]; then printf "\n\n${CYAN}Status: ${PLAIN}${RED}Docker not found. Terminating setup.${PLAIN}\n\n" - exit 1 + return 1 fi printf "\n${CYAN}Found docker. Moving on with the setup.${PLAIN}\n" @@ -57,7 +57,7 @@ printf "\n${RED}>> Starting the postgresql container${PLAIN} ${GREEN}...${PLAIN} CONTAINER_STATUS=$(docker run --name $POSTGRESQL_CONTAINER -e POSTGRES_USER=$USER -e POSTGRES_PASSWORD=$PASSWORD -p $PORT:5432 -d postgres:latest 2>&1) if [[ "$CONTAINER_STATUS" == *"Error"* ]]; then printf "\n\n${CYAN}Status: ${PLAIN}${RED}Error starting container. Terminating setup.${PLAIN}\n\n" - exit 1 + return 1 fi docker cp ./test/schema.sql $POSTGRESQL_CONTAINER:/home/ > /dev/null 2>&1 printf "\n${CYAN}Container is up and running.${PLAIN}\n" @@ -91,7 +91,7 @@ while [ "$OUTPUT" -ne 0 ] && [ "$TIMEOUT" -gt 0 ] if [ "$TIMEOUT" -le 0 ]; then printf "\n\n${CYAN}Status: ${PLAIN}${RED}Failed to export schema. Terminating setup.${PLAIN}\n\n" - exit 1 + return 1 fi printf "\n${CYAN}Successfully exported schema to database.${PLAIN}\n" @@ -102,7 +102,7 @@ docker exec -it $POSTGRESQL_CONTAINER /bin/sh -c "psql -U $USER -c 'CREATE DATAB CREATE_DATABASE=$? if [ "$CREATE_DATABASE" -ne 0 ]; then printf "\n\n${CYAN}Status: ${PLAIN}${RED}Error creating database: $DATABASE. Terminating setup.${PLAIN}\n\n" - exit 1 + return 1 fi printf "\n${CYAN}Database created.${PLAIN}\n" From 59cad94ac113b879ae6f08202ccd9b974df61e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 28 Aug 2020 09:01:53 +0200 Subject: [PATCH 49/72] update dependencies to latest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `eslint` to 7.x - `mocha` to 8.x - `uuid` to 8.x - `loopback-connector` to 5.x Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- .mocharc.json | 6 ++++++ package.json | 8 ++++---- test/mocha.opts | 4 ---- 3 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 .mocharc.json delete mode 100644 test/mocha.opts diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 00000000..5fba0f2c --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,6 @@ +{ + "reporter": "spec", + "timeout": 10000, + "require": "test/init.js", + "exit": true +} diff --git a/package.json b/package.json index 675695e3..7d1113b4 100644 --- a/package.json +++ b/package.json @@ -31,19 +31,19 @@ "bluebird": "^3.4.6", "chalk": "^4.0.0", "debug": "^4.1.1", - "loopback-connector": "^4.10.2", + "loopback-connector": "^5.0.0", "pg": "^8.0.2", "strong-globalize": "^6.0.0", - "uuid": "^7.0.3" + "uuid": "^8.3.0" }, "devDependencies": { - "eslint": "^6.0.1", + "eslint": "^7.7.0", "eslint-config-loopback": "^13.1.0", "juggler-v3": "file:./deps/juggler-v3", "juggler-v4": "file:./deps/juggler-v4", "lodash": "^4.17.4", "loopback-datasource-juggler": "^3.0.0 || ^4.0.0", - "mocha": "^7.1.1", + "mocha": "^8.1.2", "rc": "^1.0.0", "should": "^13.2.3", "sinon": "^9.0.2" diff --git a/test/mocha.opts b/test/mocha.opts deleted file mode 100644 index 9bbfff4a..00000000 --- a/test/mocha.opts +++ /dev/null @@ -1,4 +0,0 @@ ---reporter spec ---timeout 10000 ---require test/init.js ---exit From 0ac9289845aed43bdf97b01c85419954417e842b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 1 Sep 2020 14:51:58 +0200 Subject: [PATCH 50/72] 5.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update dependencies to latest (Miroslav Bajtoš) * fix setup script to not exit calling shell (Miroslav Bajtoš) * chore: switch to DCO (Diana Lau) * docs: update loopback types link (Agnes Lin) * Update .travis.yml (karanssj4) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 0a74108d..3ea5d2d3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,17 @@ +2020-09-01, Version 5.1.0 +========================= + + * update dependencies to latest (Miroslav Bajtoš) + + * fix setup script to not exit calling shell (Miroslav Bajtoš) + + * chore: switch to DCO (Diana Lau) + + * docs: update loopback types link (Agnes Lin) + + * Update .travis.yml (karanssj4) + + 2020-07-10, Version 5.0.2 ========================= diff --git a/package.json b/package.json index 7d1113b4..1a779e5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "5.0.2", + "version": "5.1.0", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=10" From 99a0005585875ce872304430ff63b96161f560dc Mon Sep 17 00:00:00 2001 From: shubhisood Date: Fri, 4 Sep 2020 01:09:50 +0530 Subject: [PATCH 51/72] feat: adds 'contains' operator for querying arrays Implement support for an extended operator `contains` that can be used to filter records that have an array property containing the selected items. Signed-off-by: shubhisood Signed-off-by: SAMI BETTAYEB --- README.md | 58 +++++++++++++++++++++++++++++++++++++++++ lib/postgresql.js | 3 +++ test/postgresql.test.js | 10 +++++++ 3 files changed, 71 insertions(+) diff --git a/README.md b/README.md index 52456ef2..80db2bc3 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,29 @@ const config = { }; ``` + +## Additional properties + +
Node.js Buffer object
SMALLINT
INTEGER
BIGINT
DECIMAL
NUMERIC
REAL
DOUBLE
SERIAL
BIGSERIAL
SMALLINT
INTEGER
BIGINT
DECIMAL
NUMERIC
REAL
DOUBLE PRECISION
FLOAT
SERIAL
BIGSERIAL
Number
+ + + + + + + + + + + + + + + + +
PropertyTypeDefaultDescription
allowExtendedOperatorsBooleanfalseSet to true to enable using Postgres operators such as contains which is used to perform filter on postgres array type field.
+ + ## Defining models LoopBack allows you to specify some database settings through the model definition and/or the property definition. These definitions would be mapped to the database. Please check out the CLI [`lb4 model`](https://loopback.io/doc/en/lb4/Model-generator.html) for generating LB4 models. The following is a typical LoopBack 4 model that specifies the schema, table and column details through model definition and property definitions: @@ -412,6 +435,12 @@ details on LoopBack's data types. VARCHAR2
Default length is 1024
String[] + VARCHAR2[] +
Number
@@ -106,7 +106,7 @@ Check out [node-pg-pool](https://github.com/brianc/node-pg-pool) and [node postg - + @@ -176,6 +176,14 @@ Check out [node-pg-pool](https://github.com/brianc/node-pg-pool) and [node postg + + + + +
Description
connector StringBoolean/String Set to false to disable default sorting on id column(s). Set to numericIdOnly to only apply to IDs with a number type id.
allowExtendedOperatorsBooleanSet to true to enable PostgreSQL-specific operators + such as contains. Learn more in + Extended operators below. +
@@ -202,29 +210,6 @@ const config = { }; ``` - -## Additional properties - - - - - - - - - - - - - - - - - - -
PropertyTypeDefaultDescription
allowExtendedOperatorsBooleanfalseSet to true to enable using Postgres operators such as contains which is used to perform filter on postgres array type field.
- - ## Defining models LoopBack allows you to specify some database settings through the model definition and/or the property definition. These definitions would be mapped to the database. Please check out the CLI [`lb4 model`](https://loopback.io/doc/en/lb4/Model-generator.html) for generating LB4 models. The following is a typical LoopBack 4 model that specifies the schema, table and column details through model definition and property definitions: @@ -295,7 +280,7 @@ The model definition consists of the following properties. Description - + name Camel-case of the database table name @@ -560,43 +545,65 @@ CustomerRepository.find({ }); ``` -## Querying Postgres Array type fields +## Extended operators + +PostgreSQL supports the following PostgreSQL-specific operators: + +- [`contains`](#operator-contains) + +Please note extended operators are disabled by default, you must enable +them at datasource level or model level by setting `allowExtendedOperators` to +`true`. + +### Operator `contains` -**Note** The fields you are querying should be setup to use the postgresql array data type - see Defining models +The `contains` operator allow you to query array properties and pick only +rows where the stored value contains all of the items specified by the query. + +The operator is implemented using PostgreSQL [array operator +`@>`](https://www.postgresql.org/docs/current/functions-array.html). + +**Note** The fields you are querying must be setup to use the postgresql array data type - see [Defining models](#defining-models) above. Assuming a model such as this: ```ts +@model({ + settings: { + allowExtendedOperators: true, + } +}) +class Post { @property({ type: ['string'], postgresql: { - dataType: 'varchar[]', - }, + dataType: 'varchar[]', + }, }) categories?: string[]; +} ``` -You can query the tags fields via setting allowExtendedOperators to true +You can query the tags fields as follows: ```ts -Model.dataSource.settings.allowExtendedOperators = true; - const post = await Post.find({where: { - { - categories: {'contains': ['AA']}, - } - } - }); +const posts = await postRepository.find({ + where: { + { + categories: {'contains': ['AA']}, + } + } +}); ``` - ## Discovery and auto-migration ### Model discovery The PostgreSQL connector supports _model discovery_ that enables you to create LoopBack models based on an existing database schema. Once you defined your datasource: -- LoopBack 4 users could use the commend [`lb4 discover`](https://loopback.io/doc/en/lb4/Discovering-models.html) to discover models. -- For LB3 users, please check [Discovering models from relational databases](https://loopback.io/doc/en/lb3/Discovering-models-from-relational-databases.html). +- LoopBack 4 users could use the commend [`lb4 discover`](https://loopback.io/doc/en/lb4/Discovering-models.html) to discover models. +- For LB3 users, please check [Discovering models from relational databases](https://loopback.io/doc/en/lb3/Discovering-models-from-relational-databases.html). (See [database discovery API](http://apidocs.strongloop.com/loopback-datasource-juggler/#datasource-prototype-discoverandbuildmodels) for related APIs information) @@ -670,7 +677,7 @@ Here are some limitations and tips: ### Auto-migrate/Auto-update models with foreign keys -Foreign key constraints can be defined in the model definition. +Foreign key constraints can be defined in the model definition. **Note**: The order of table creation is important. A referenced table must exist before creating a foreign key constraint. From ca1110aa2232593937707eae0e3379bf40b4b294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 6 Oct 2020 11:33:06 +0200 Subject: [PATCH 53/72] test: fix array tests to handle List values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Array properties are represented as juggler `List` instance, we need to modify test assertions to convert them via `toArray()` before applying `.should.eql` check. Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- test/postgresql.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/postgresql.test.js b/test/postgresql.test.js index 8e5a5606..c710a567 100644 --- a/test/postgresql.test.js +++ b/test/postgresql.test.js @@ -218,7 +218,7 @@ describe('postgresql connector', function() { post.should.have.property('tags'); post.tags.should.be.Array(); post.tags.length.should.eql(2); - post.tags.should.eql(['AA', 'AB']); + post.tags.toArray().should.eql(['AA', 'AB']); return Post.updateAll({where: {id: postId}}, {tags: ['AA', 'AC']}); }) .then(()=> { @@ -228,7 +228,7 @@ describe('postgresql connector', function() { post.should.have.property('tags'); post.tags.should.be.Array(); post.tags.length.should.eql(2); - post.tags.should.eql(['AA', 'AC']); + post.tags.toArray().should.eql(['AA', 'AC']); done(); }) .catch((error) => { @@ -245,7 +245,7 @@ describe('postgresql connector', function() { post.should.have.property('categories'); post.categories.should.be.Array(); post.categories.length.should.eql(2); - post.categories.should.eql(['AA', 'AB']); + post.categories.toArray().should.eql(['AA', 'AB']); return Post.updateAll({where: {id: postId}}, {categories: ['AA', 'AC']}); }) .then(()=> { @@ -255,7 +255,7 @@ describe('postgresql connector', function() { post.should.have.property('categories'); post.categories.should.be.Array(); post.categories.length.should.eql(2); - post.categories.should.eql(['AA', 'AC']); + post.categories.toArray().should.eql(['AA', 'AC']); done(); }) .catch((error) => { From 4b434bc3de75f7656886acef7f9689b518aed072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 6 Oct 2020 11:34:22 +0200 Subject: [PATCH 54/72] test: clean test for `contains` operator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- test/postgresql.test.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/test/postgresql.test.js b/test/postgresql.test.js index c710a567..bd442167 100644 --- a/test/postgresql.test.js +++ b/test/postgresql.test.js @@ -73,7 +73,7 @@ describe('postgresql connector', function() { dataType: 'varchar[]', }, }, - }); + }, {allowExtendedOperators: true}); created = new Date(); }); @@ -264,15 +264,23 @@ describe('postgresql connector', function() { }); it('should support where filter for array type field', async () => { - Post.dataSource.settings.allowExtendedOperators = true; - const post = await Post.find({where: {and: [ + await Post.create({ + title: 'LoopBack Participates in Hacktoberfest', + categories: ['LoopBack', 'Announcements'], + }); + await Post.create({ + title: 'Growing LoopBack Community', + categories: ['LoopBack', 'Community'], + }); + + const found = await Post.find({where: {and: [ { - categories: {'contains': ['AA']}, + categories: {'contains': ['LoopBack', 'Community']}, }, ]}}); - should.exist(post); - post.length.should.equal(1); + found.map(p => p.title).should.deepEqual(['Growing LoopBack Community']); }); + it('should support boolean types with false value', function(done) { Post.create( {title: 'T2', content: 'C2', approved: false, created: created}, From 8ad72a5f3191a71aeba5c1eb4d966aace67ee1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 6 Oct 2020 18:53:27 +0200 Subject: [PATCH 55/72] 5.2.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: clean test for `contains` operator (Miroslav Bajtoš) * test: fix array tests to handle List values (Miroslav Bajtoš) * docs: improve README organization (Miroslav Bajtoš) * feat: adds 'contains' operator for querying arrays (shubhisood) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 3ea5d2d3..27d15931 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,15 @@ +2020-10-06, Version 5.2.0 +========================= + + * test: clean test for `contains` operator (Miroslav Bajtoš) + + * test: fix array tests to handle List values (Miroslav Bajtoš) + + * docs: improve README organization (Miroslav Bajtoš) + + * feat: adds 'contains' operator for querying arrays (shubhisood) + + 2020-09-01, Version 5.1.0 ========================= diff --git a/package.json b/package.json index 1a779e5d..b7836b31 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "5.1.0", + "version": "5.2.0", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=10" From 0edc5585a218f334db0c14a2f2cf9942e69ff314 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Mon, 9 Nov 2020 12:54:35 -0800 Subject: [PATCH 56/72] Ensure order of and/or clauses are preserved Signed-off-by: Raymond Feng Signed-off-by: SAMI BETTAYEB --- lib/postgresql.js | 2 +- test/postgresql.test.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/postgresql.js b/lib/postgresql.js index 8673e9f5..8dec0c46 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -612,7 +612,7 @@ PostgreSQL.prototype._buildWhere = function(model, where) { } } stmt.merge({ - sql: branches.join(' ' + key.toUpperCase() + ' '), + sql: '(' + branches.join(' ' + key.toUpperCase() + ' ') + ')', params: branchParams, }); whereStmts.push(stmt); diff --git a/test/postgresql.test.js b/test/postgresql.test.js index bd442167..2d1fadd3 100644 --- a/test/postgresql.test.js +++ b/test/postgresql.test.js @@ -423,6 +423,14 @@ describe('postgresql connector', function() { done(); }); }); + + it('should preserve order of and/or in where', async function() { + await Post.create({title: 'T3', content: 'C3', approved: false}); + // WHERE (title='T3' OR approved=false) AND (content='C2') + const posts = await Post.find({where: {or: [{title: 'T3'}, + {approved: false}], content: 'C2'}}); + posts.length.should.equal(0); + }); }); context('pattern matching operators', function() { From 26e2a73411b440e3603017009e86034c52dece81 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Tue, 10 Nov 2020 08:11:57 -0800 Subject: [PATCH 57/72] 5.2.1 * Ensure order of and/or clauses are preserved (Raymond Feng) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 27d15931..116906f5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +2020-11-10, Version 5.2.1 +========================= + + * Ensure order of and/or clauses are preserved (Raymond Feng) + + 2020-10-06, Version 5.2.0 ========================= diff --git a/package.json b/package.json index b7836b31..c965ac74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "5.2.0", + "version": "5.2.1", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=10" From 7d2ba32ec74e180390f6cb868251de77beb8f296 Mon Sep 17 00:00:00 2001 From: Matthew Gabeler-Lee Date: Wed, 2 Dec 2020 18:27:12 -0500 Subject: [PATCH 58/72] fix: enable pool error handling Signed-off-by: Matthew Gabeler-Lee Signed-off-by: SAMI BETTAYEB --- lib/postgresql.js | 14 ++++++++++++- test/postgresql.initialization.test.js | 28 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/postgresql.js b/lib/postgresql.js index 8dec0c46..2ac994f2 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -54,7 +54,7 @@ exports.initialize = function initializeDataSource(dataSource, callback) { * * @param {PostgreSQL} postgresql PostgreSQL node.js binding * @options {Object} settings An object for the data source settings. - * See [node-postgres documentation](https://github.com/brianc/node-postgres/wiki/Client#parameters). + * See [node-postgres documentation](https://node-postgres.com/api/client). * @property {String} url URL to the database, such as 'postgres://test:mypassword@localhost:5432/devdb'. * Other parameters can be defined as query string of the url * @property {String} hostname The host name or ip address of the PostgreSQL DB server @@ -63,6 +63,8 @@ exports.initialize = function initializeDataSource(dataSource, callback) { * @property {String} password The password * @property {String} database The database name * @property {Boolean} ssl Whether to try SSL/TLS to connect to server + * @property {Function | string} [onError] Optional hook to connect to the pg pool 'error' event, + * or the string 'ignore' to record them with `debug` and otherwise ignore them. * * @constructor */ @@ -79,6 +81,16 @@ function PostgreSQL(postgresql, settings) { this.clientConfig.Promise = Promise; this.pg = new postgresql.Pool(this.clientConfig); + if (settings.onError) { + if (settings.onError === 'ignore') { + this.pg.on('error', function(err) { + debug(err); + }); + } else { + this.pg.on('error', settings.onError); + } + } + this.settings = settings; debug('Settings %j', settings); } diff --git a/test/postgresql.initialization.test.js b/test/postgresql.initialization.test.js index f5a431b6..32084a6d 100644 --- a/test/postgresql.initialization.test.js +++ b/test/postgresql.initialization.test.js @@ -83,4 +83,32 @@ describe('postgresql connector errors', function() { done(); }); }); + + it('honours onError=ignore', function() { + const settings = newConfig(); + settings.onError = 'ignore'; + + const dataSource = new DataSource(connector, settings); + + dataSource.connector.pg.listenerCount('error').should.equal(1); + }); + + it('honours onError=listener', function() { + const settings = newConfig(); + let errorsCaught = 0; + settings.onError = function(err, client) { + err.should.be.ok(); + client.should.be.ok(); + ++errorsCaught; + }; + + const dataSource = new DataSource(connector, settings); + + dataSource.connector.pg.listenerCount('error').should.equal(1); + dataSource.connector.pg.listeners('error').should.deepEqual([settings.onError]); + + // send a fake error in and make sure it is bound to our listener + dataSource.connector.pg.emit('error', new Error('fake error'), {fakeClient: true}); + errorsCaught.should.equal(1); + }); }); From 98df623bc35354b4816bd43d7fb87d7a40d33cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 7 Dec 2020 14:07:44 +0100 Subject: [PATCH 59/72] 5.3.0 * fix: enable pool error handling (Matthew Gabeler-Lee) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 116906f5..74cd6fad 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +2020-12-07, Version 5.3.0 +========================= + + * fix: enable pool error handling (Matthew Gabeler-Lee) + + 2020-11-10, Version 5.2.1 ========================= diff --git a/package.json b/package.json index c965ac74..e952e053 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "5.2.1", + "version": "5.3.0", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=10" From 09ed542291ca240d7c9ee19595822a3ccf4ea2cc Mon Sep 17 00:00:00 2001 From: Francisco Buceta Date: Mon, 1 Feb 2021 01:38:35 +0100 Subject: [PATCH 60/72] ci: switch travis to github actions Signed-off-by: Francisco Buceta Signed-off-by: SAMI BETTAYEB --- .github/workflows/continuous-integration.yml | 32 ++++++++++++++++++++ .travis.yml | 18 ----------- 2 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/continuous-integration.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 00000000..e8ee33f5 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,32 @@ +name: Continuous Integration + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + node-version: [10.x, 12.x, 14.x, 15.x] + services: + postgres: + image: postgres:9.6 + env: + POSTGRES_HOST_AUTH_METHOD: trust + ports: + - 5432:5432 + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test + env: + PGUSER: postgres diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2f34419a..00000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: node_js -node_js: - - "10" - - "12" - - "13" - - "14" - -services: - - postgresql -addons: - postgresql: "9.6" -env: - global: - - PGUSER=postgres - -branches: - only: - - master From 9902bee8572d7f492fee8f6795668d1b2b052549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 2 Feb 2021 13:23:39 +0100 Subject: [PATCH 61/72] Revert "ci: switch travis to github actions" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e3ba700b8acdd48195f293e2e795e2bbc56a311a. Signed-off-by: Miroslav Bajtoš Signed-off-by: SAMI BETTAYEB --- .github/workflows/continuous-integration.yml | 32 -------------------- .travis.yml | 18 +++++++++++ 2 files changed, 18 insertions(+), 32 deletions(-) delete mode 100644 .github/workflows/continuous-integration.yml create mode 100644 .travis.yml diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml deleted file mode 100644 index e8ee33f5..00000000 --- a/.github/workflows/continuous-integration.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Continuous Integration - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - node-version: [10.x, 12.x, 14.x, 15.x] - services: - postgres: - image: postgres:9.6 - env: - POSTGRES_HOST_AUTH_METHOD: trust - ports: - - 5432:5432 - steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - - run: npm install - - run: npm test - env: - PGUSER: postgres diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..2f34419a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: node_js +node_js: + - "10" + - "12" + - "13" + - "14" + +services: + - postgresql +addons: + postgresql: "9.6" +env: + global: + - PGUSER=postgres + +branches: + only: + - master From cb5cee06ba200de76c2693c788cb57aaea5335ad Mon Sep 17 00:00:00 2001 From: Agnes Lin Date: Fri, 12 Feb 2021 15:08:47 -0500 Subject: [PATCH 62/72] ci: switch from Travis to Github Actions Signed-off-by: Agnes Lin Signed-off-by: SAMI BETTAYEB --- .github/workflows/continuous-integration.yaml | 32 +++++++++++++++++++ .travis.yml | 18 ----------- 2 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/continuous-integration.yaml delete mode 100644 .travis.yml diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml new file mode 100644 index 00000000..ebad8237 --- /dev/null +++ b/.github/workflows/continuous-integration.yaml @@ -0,0 +1,32 @@ +name: Continuous Integration + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + node-version: [10, 12, 14, 15] + services: + postgres: + image: postgres:latest + env: + POSTGRES_HOST_AUTH_METHOD: trust + ports: + - 5432:5432 + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - run: npm install + - run: npm test + env: + PGUSER: postgres diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2f34419a..00000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: node_js -node_js: - - "10" - - "12" - - "13" - - "14" - -services: - - postgresql -addons: - postgresql: "9.6" -env: - global: - - PGUSER=postgres - -branches: - only: - - master From 33de0e26486045f95bfc2e56ee32436af284ca74 Mon Sep 17 00:00:00 2001 From: Quentin Le Bour Date: Wed, 2 Sep 2020 14:28:00 +0200 Subject: [PATCH 63/72] Add on delete options on FK constraints Signed-off-by: Agnes Lin Signed-off-by: SAMI BETTAYEB --- README.md | 8 ++++++-- lib/discovery.js | 6 ++++++ lib/migration.js | 24 +++++++++++++++++++++--- test/postgresql.autoupdate.test.js | 6 ++++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0aa11976..95072031 100644 --- a/README.md +++ b/README.md @@ -713,6 +713,8 @@ export class Customer extends Entity { entity: 'Customer', entityKey: 'id', foreignKey: 'customerId', + onDelete: 'CASCADE', + onUpdate: 'SET NULL' }, }, }) @@ -764,7 +766,9 @@ export class Order extends Entity { "name": "fk_order_customerId", "entity": "Customer", "entityKey": "id", - "foreignKey": "customerId" + "foreignKey": "customerId", + "onDelete": "CASCADE", + "onUpdate": "SET NULL" } } }, @@ -787,7 +791,7 @@ export class Order extends Entity {
{% include tip.html content=" -Removing or updating the value of `foreignKeys` will be updated or delete or update the constraints in the db tables. If there is a reference to an object being deleted then the `DELETE` will fail. Likewise if there is a create with an invalid FK id then the `POST` will fail. +Removing or updating the value of `foreignKeys` will be updated or delete or update the constraints in the db tables. If there is a reference to an object being deleted then the `DELETE` will fail. Likewise if there is a create with an invalid FK id then the `POST` will fail. The `onDelete` and `onUpdate` properties are optional and will default to `NO ACTION`. " %} ### Auto-generated ids diff --git a/lib/discovery.js b/lib/discovery.js index ed01ca02..a10454d7 100644 --- a/lib/discovery.js +++ b/lib/discovery.js @@ -263,6 +263,7 @@ function mixinDiscovery(PostgreSQL) { let sql = 'SELECT tc.table_schema AS "fkOwner", tc.constraint_name AS "fkName", tc.table_name AS "fkTableName",' + ' kcu.column_name AS "fkColumnName", kcu.ordinal_position AS "keySeq",' + + ' rcu.delete_rule AS "onDelete", rcu.update_rule AS "onUpdate",' + ' ccu.table_schema AS "pkOwner",' + ' (SELECT constraint_name' + ' FROM information_schema.table_constraints tc2' @@ -273,6 +274,8 @@ function mixinDiscovery(PostgreSQL) { + ' ON tc.constraint_schema = kcu.constraint_schema AND tc.constraint_name = kcu.constraint_name' + ' JOIN information_schema.constraint_column_usage ccu' + ' ON ccu.constraint_schema = tc.constraint_schema AND ccu.constraint_name = tc.constraint_name' + + ' JOIN information_schema.referential_constraints AS rcu' + + ' ON rcu.constraint_name = tc.constraint_name' + ' WHERE tc.constraint_type = \'FOREIGN KEY\''; if (owner) { sql += ' AND tc.table_schema=\'' + owner + '\''; @@ -300,6 +303,7 @@ function mixinDiscovery(PostgreSQL) { PostgreSQL.prototype.buildQueryExportedForeignKeys = function(owner, table) { let sql = 'SELECT kcu.constraint_name AS "fkName", kcu.table_schema AS "fkOwner", kcu.table_name AS "fkTableName",' + ' kcu.column_name AS "fkColumnName", kcu.ordinal_position AS "keySeq",' + + ' rcu.delete_rule AS "onDelete", rcu.update_rule AS "onUpdate",' + ' (SELECT constraint_name' + ' FROM information_schema.table_constraints tc2' + ' WHERE tc2.constraint_type = \'PRIMARY KEY\' and tc2.table_name=ccu.table_name limit 1) AS "pkName",' @@ -308,6 +312,8 @@ function mixinDiscovery(PostgreSQL) { + ' information_schema.constraint_column_usage ccu' + ' JOIN information_schema.key_column_usage kcu' + ' ON ccu.constraint_schema = kcu.constraint_schema AND ccu.constraint_name = kcu.constraint_name' + + ' JOIN information_schema.referential_constraints AS rcu' + + ' ON rcu.constraint_name = tc.constraint_name' + ' WHERE kcu.position_in_unique_constraint IS NOT NULL'; if (owner) { sql += ' and ccu.table_schema=\'' + owner + '\''; diff --git a/lib/migration.js b/lib/migration.js index 2e16d0cf..55182050 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -574,7 +574,9 @@ function mixinMigration(PostgreSQL) { const fkRefTable = self.table(fkEntityName); needsToDrop = !isCaseInsensitiveEqual(fkCol, fk.fkColumnName) || !isCaseInsensitiveEqual(fkRefKey, fk.pkColumnName) || - !isCaseInsensitiveEqual(fkRefTable, fk.pkTableName); + !isCaseInsensitiveEqual(fkRefTable, fk.pkTableName) || + parseAction(newFk.onDelete) != fk.onDelete || + parseAction(newFk.onUpdate) != fk.onUpdate; } else { // FK will be dropped if column is removed // only if FK is in model properties then need to drop @@ -636,13 +638,29 @@ function mixinMigration(PostgreSQL) { // verify that the other model in the same DB if (this._models[fkEntityName]) { return 'CONSTRAINT ' + this.escapeName(fk.name) + ' ' + - 'FOREIGN KEY (' + this.escapeName(fk.foreignKey) + ') ' + - 'REFERENCES ' + this.tableEscaped(fkEntityName) + '(' + fk.entityKey + ')'; + 'FOREIGN KEY (' + this.escapeName(fk.foreignKey) + ') ' + + 'REFERENCES ' + this.tableEscaped(fkEntityName) + '(' + fk.entityKey + ') ' + + 'ON DELETE ' + parseAction(fk.onDelete) + ' ' + + 'ON UPDATE ' + parseAction(fk.onUpdate); } } return ''; }; + /*! + * Process model settings foreign key action, + * if action is not a valid sql action return 'NO ACTION' + * @param {Any} action + */ + function parseAction(action) { + if (typeof action !== 'string') return 'NO ACTION'; + const _action = action.toUpperCase(); + if (['RESTRICT', 'CASCADE', 'SET NULL', 'SET DEFAULT'].includes(_action)) + return _action; + else + return 'NO ACTION'; + } + /*! * Case insensitive comparison of two strings * @param {String} val1 diff --git a/test/postgresql.autoupdate.test.js b/test/postgresql.autoupdate.test.js index b1a75ce7..d90f285e 100644 --- a/test/postgresql.autoupdate.test.js +++ b/test/postgresql.autoupdate.test.js @@ -469,6 +469,8 @@ describe('autoupdate', function() { 'entity': 'Product', 'entityKey': 'id', 'foreignKey': 'productId', + 'onDelete': 'CASCADE', + 'onUpdate': 'SET NULL', }, }, }, @@ -578,6 +580,8 @@ describe('autoupdate', function() { assert.equal(foreignKeys[0].pkTableName, 'customer_test2'); assert.equal(foreignKeys[0].fkColumnName, 'customerId'); assert.equal(foreignKeys[0].fkName, 'fk_ordertest_customerId'); + assert.equal(foreignKeys[0].onDelete, 'NO ACTION'); + assert.equal(foreignKeys[0].onUpdate, 'NO ACTION'); // update the fk of model OrderTest from customerId to productId // productId refers to model Product @@ -596,6 +600,8 @@ describe('autoupdate', function() { assert.equal(foreignKeys[0].pkTableName, 'product_test'); assert.equal(foreignKeys[0].fkColumnName, 'productId'); assert.equal(foreignKeys[0].fkName, 'fk_ordertest_productId'); + assert.equal(foreignKeys[0].onDelete, 'CASCADE'); + assert.equal(foreignKeys[0].onUpdate, 'SET NULL'); // remove fk from model OrderTest ds.createModel(orderTest_schema_v3.name, orderTest_schema_v3.properties, From bf6067e809daba221867554f1a311e24b336bf03 Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Mon, 3 May 2021 10:50:16 -0400 Subject: [PATCH 64/72] 5.4.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add on delete options on FK constraints (Quentin Le Bour) * ci: switch from Travis to Github Actions (Agnes Lin) * Revert "ci: switch travis to github actions" (Miroslav Bajtoš) * ci: switch travis to github actions (Francisco Buceta) Signed-off-by: SAMI BETTAYEB --- CHANGES.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 74cd6fad..801f57fe 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,15 @@ +2021-05-03, Version 5.4.0 +========================= + + * Add on delete options on FK constraints (Quentin Le Bour) + + * ci: switch from Travis to Github Actions (Agnes Lin) + + * Revert "ci: switch travis to github actions" (Miroslav Bajtoš) + + * ci: switch travis to github actions (Francisco Buceta) + + 2020-12-07, Version 5.3.0 ========================= diff --git a/package.json b/package.json index e952e053..97ebaaae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-connector-postgresql", - "version": "5.3.0", + "version": "5.4.0", "description": "Loopback PostgreSQL Connector", "engines": { "node": ">=10" From ce924be6ea3489bb339cccfea47bf5350e0d0a78 Mon Sep 17 00:00:00 2001 From: Chris Kobrzak Date: Sun, 4 Jul 2021 23:57:34 +0100 Subject: [PATCH 65/72] Defensively drop constraints during migrations When `PostgreSQL.prototype.getDropForeignKeys` gets called with duplicated foreign keys, an invalid `ALTER TABLE` statement gets created. This is because the duplicates are mapped to multiple `DROP CONSTRAINT fk_key` SQL actions, e.g.: ```sql -- This will throw an error ALTER TABLE "public"."foo" DROP CONSTRAINT "fk_duplicatedKey", DROP CONSTRAINT "fk_duplicatedKey", DROP CONSTRAINT "fk_duplicatedKey", DROP CONSTRAINT "fk_otherKey" ``` As the `DROP CONSTRAINT` actions are run sequentially, when the first action gets executed by PostgreSQL, the next one (for the same, but already dropped key) will not cause an SQL error thanks to the added IF EXISTS check: ```sql -- This is valid SQL ALTER TABLE "public"."foo" DROP CONSTRAINT IF EXISTS "fk_duplicatedKey", DROP CONSTRAINT IF EXISTS "fk_duplicatedKey", DROP CONSTRAINT IF EXISTS "fk_duplicatedKey", DROP CONSTRAINT IF EXISTS "fk_otherKey" ``` Please note, this is really a hack and we still need to understand why the method in question gets called with duplicated foreign keys in certain conditions. Signed-off-by: Chris Kobrzak Signed-off-by: SAMI BETTAYEB --- lib/migration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/migration.js b/lib/migration.js index 55182050..57ad4310 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -586,7 +586,7 @@ function mixinMigration(PostgreSQL) { } if (needsToDrop) { - sql.push('DROP CONSTRAINT ' + self.escapeName(fk.fkName)); + sql.push('DROP CONSTRAINT IF EXISTS ' + self.escapeName(fk.fkName)); removedFks.push(fk); // keep track that we removed these } From 2994e4e8d7321d07525660d4ceb1a571fa26b4bd Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Mon, 12 Jul 2021 13:25:00 -0400 Subject: [PATCH 66/72] chore: move repo to loopbackio org Signed-off-by: Diana Lau Signed-off-by: SAMI BETTAYEB --- .github/ISSUE_TEMPLATE/Question.md | 5 - .github/workflows/continuous-integration.yaml | 35 +- .npmrc | 1 - CONTRIBUTING.md | 2 +- README.md | 2 +- commitlint.config.js | 18 + package-lock.json | 6237 +++++++++++++++++ package.json | 6 +- 8 files changed, 6294 insertions(+), 12 deletions(-) delete mode 100644 .npmrc create mode 100644 commitlint.config.js create mode 100644 package-lock.json diff --git a/.github/ISSUE_TEMPLATE/Question.md b/.github/ISSUE_TEMPLATE/Question.md index eb25195a..189219e8 100644 --- a/.github/ISSUE_TEMPLATE/Question.md +++ b/.github/ISSUE_TEMPLATE/Question.md @@ -19,9 +19,4 @@ Please use one of the following resources for help: - https://groups.google.com/forum/#!forum/loopbackjs - https://gitter.im/strongloop/loopback -**Immediate support** - -- https://strongloop.com/api-connect-faqs/ -- https://strongloop.com/node-js/subscription-plans/ - --> diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index ebad8237..9fe0c54c 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -12,7 +12,7 @@ jobs: strategy: matrix: # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - node-version: [10, 12, 14, 15] + node-version: [12, 14, 16] services: postgres: image: postgres:latest @@ -30,3 +30,36 @@ jobs: - run: npm test env: PGUSER: postgres + code-lint: + name: Code Lint + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: 14 + - name: Bootstrap project + run: | + npm ci --ignore-scripts + - name: Verify code linting + run: npm run lint + + commit-lint: + name: Commit Lint + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: 14 + - name: Bootstrap project + run: | + npm ci --ignore-scripts + - name: Verify commit linting + run: npx commitlint --from origin/master --to HEAD --verbose diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 43c97e71..00000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbc10d03..16dddde0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ Contributing to `loopback-connector-postgresql` is easy. In a few simple steps: * Adhere to code style outlined in the [Google C++ Style Guide][] and [Google Javascript Style Guide][]. - * Sign the [Contributor License Agreement](https://cla.strongloop.com/agreements/strongloop/loopback-connector-postgresql) + * Sign the [Developer Certificate of Origin](#developer-certificate-of-origin) * Submit a pull request through Github. diff --git a/README.md b/README.md index 95072031..788ed715 100644 --- a/README.md +++ b/README.md @@ -470,7 +470,7 @@ Besides the basic LoopBack types, as we introduced above, you can also specify t {% include warning.html content=" -Not all database types are supported for operating CRUD operations and queries with filters. For example, type Array cannot be filtered correctly, see GitHub issues: [# 441](https://github.com/strongloop/loopback-connector-postgresql/issues/441) and [# 342](https://github.com/strongloop/loopback-connector-postgresql/issues/342). +Not all database types are supported for operating CRUD operations and queries with filters. For example, type Array cannot be filtered correctly, see GitHub issues: [# 441](https://github.com/loopbackio/loopback-connector-postgresql/issues/441) and [# 342](https://github.com/loopbackio/loopback-connector-postgresql/issues/342). " %} ### PostgreSQL types to LoopBack diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..8e11d956 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,18 @@ +// Copyright IBM Corp. 2021. All Rights Reserved. +// Node module: loopback-connector-postgresql +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +'use strict'; + +module.exports = { + extends: [ + '@commitlint/config-conventional', + ], + rules: { + 'header-max-length': [2, 'always', 100], + 'body-leading-blank': [2, 'always'], + 'footer-leading-blank': [0, 'always'], + 'signed-off-by': [2, 'always', 'Signed-off-by:'], + }, +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..5f2b6d03 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6237 @@ +{ + "name": "loopback-connector-postgresql", + "version": "5.4.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "version": "5.4.0", + "license": "Artistic-2.0", + "dependencies": { + "async": "^3.2.0", + "bluebird": "^3.4.6", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "loopback-connector": "^5.0.0", + "pg": "^8.0.2", + "strong-globalize": "^6.0.0", + "uuid": "^8.3.0" + }, + "devDependencies": { + "@commitlint/config-conventional": "^12.1.4", + "eslint": "^7.7.0", + "eslint-config-loopback": "^13.1.0", + "juggler-v3": "file:./deps/juggler-v3", + "juggler-v4": "file:./deps/juggler-v4", + "lodash": "^4.17.4", + "loopback-datasource-juggler": "^3.0.0 || ^4.0.0", + "mocha": "^8.1.2", + "rc": "^1.0.0", + "should": "^13.2.3", + "sinon": "^9.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "deps/juggler-v3": { + "version": "3.0.0", + "dev": true, + "dependencies": { + "loopback-datasource-juggler": "3.x", + "should": "^8.4.0" + } + }, + "deps/juggler-v3/node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "deps/juggler-v3/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "deps/juggler-v3/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "deps/juggler-v3/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "deps/juggler-v3/node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "deps/juggler-v3/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "deps/juggler-v3/node_modules/invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "deps/juggler-v3/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "deps/juggler-v3/node_modules/lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "dependencies": { + "invert-kv": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "deps/juggler-v3/node_modules/loopback-connector": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-4.11.1.tgz", + "integrity": "sha512-EA31zur3xIhP4UW+P2rWEcSbqpk4jPddpTBZSSw8KCszM7T0/Pe4HvEmG0MndAWJctRPtrwKDEu/8rWuMDLf+A==", + "dev": true, + "dependencies": { + "async": "^3.2.0", + "bluebird": "^3.7.2", + "debug": "^4.1.1", + "msgpack5": "^4.2.0", + "strong-globalize": "^5.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=8.9" + } + }, + "deps/juggler-v3/node_modules/loopback-connector/node_modules/async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + }, + "deps/juggler-v3/node_modules/loopback-connector/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "deps/juggler-v3/node_modules/loopback-connector/node_modules/strong-globalize": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-5.1.0.tgz", + "integrity": "sha512-9cooAb6kNMDFmTDybkkch1x7b+LuzZNva8oIr+MxXnvx9jcvw4/4DTSXPc53mG68G0Q9YOTYZkhDkWe/DiJ1Qg==", + "dev": true, + "dependencies": { + "accept-language": "^3.0.18", + "debug": "^4.1.1", + "globalize": "^1.5.0", + "lodash": "^4.17.15", + "md5": "^2.2.1", + "mkdirp": "^0.5.5", + "os-locale": "^5.0.0", + "yamljs": "^0.3.0" + }, + "engines": { + "node": ">=8.9" + } + }, + "deps/juggler-v3/node_modules/loopback-connector/node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "deps/juggler-v3/node_modules/loopback-datasource-juggler": { + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/loopback-datasource-juggler/-/loopback-datasource-juggler-3.36.1.tgz", + "integrity": "sha512-6eop3qxFyN3AkPBPUte2DHcsW1DopJwXXA20x3vwYsBSo4hLSv4gIeXo0+yqdQoXpHfbKRB9cv1hHEHAQSiWUA==", + "dev": true, + "dependencies": { + "async": "^2.6.0", + "bluebird": "^3.1.1", + "debug": "^3.1.0", + "depd": "^1.0.0", + "inflection": "^1.6.0", + "lodash": "^4.17.4", + "loopback-connector": "^4.4.0", + "minimatch": "^3.0.3", + "qs": "^6.5.0", + "shortid": "^2.2.6", + "strong-globalize": "^4.1.1", + "traverse": "^0.6.6", + "uuid": "^3.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "deps/juggler-v3/node_modules/mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "deps/juggler-v3/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "deps/juggler-v3/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "deps/juggler-v3/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "deps/juggler-v3/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "deps/juggler-v3/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "deps/juggler-v3/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "deps/juggler-v3/node_modules/should": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/should/-/should-8.4.0.tgz", + "integrity": "sha1-XmCInT5kS73Tl6MM00+tKPz5C8A=", + "dev": true, + "dependencies": { + "should-equal": "0.8.0", + "should-format": "0.3.2", + "should-type": "0.2.0" + } + }, + "deps/juggler-v3/node_modules/should-equal": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-0.8.0.tgz", + "integrity": "sha1-o/BXMv9FusG3ukEvhAiFaBlkEpk=", + "dev": true, + "dependencies": { + "should-type": "0.2.0" + } + }, + "deps/juggler-v3/node_modules/should-format": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-0.3.2.tgz", + "integrity": "sha1-pZgx4Bot3uFJkRvHFIvlyAMZ4f8=", + "dev": true, + "dependencies": { + "should-type": "0.2.0" + } + }, + "deps/juggler-v3/node_modules/should-type": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz", + "integrity": "sha1-ZwfvlVKdmJ3MCY/gdTqx+RNrt/Y=", + "dev": true + }, + "deps/juggler-v3/node_modules/strong-globalize": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-4.1.3.tgz", + "integrity": "sha512-SJegV7w5D4AodEspZJtJ7rls3fmi+Zc0PdyJCqBsg4RN9B8TC80/uAI2fikC+s1Jp9FLvr2vDX8f0Fqc62M4OA==", + "dev": true, + "dependencies": { + "accept-language": "^3.0.18", + "debug": "^4.1.1", + "globalize": "^1.4.2", + "lodash": "^4.17.4", + "md5": "^2.2.1", + "mkdirp": "^0.5.1", + "os-locale": "^3.1.0", + "yamljs": "^0.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "deps/juggler-v3/node_modules/strong-globalize/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "deps/juggler-v3/node_modules/strong-globalize/node_modules/os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "dependencies": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "deps/juggler-v3/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "deps/juggler-v3/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "deps/juggler-v4": { + "version": "4.0.0", + "dev": true, + "dependencies": { + "loopback-datasource-juggler": "4.x", + "should": "^13.2.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/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, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/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, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/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, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "12.1.4", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-12.1.4.tgz", + "integrity": "sha512-ZIdzmdy4o4WyqywMEpprRCrehjCSQrHkaRTVZV411GyLigFQHlEBSJITAihLAWe88Qy/8SyoIe5uKvAsV5vRqQ==", + "dev": true, + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.3.1" + }, + "engines": { + "node": ">=v10" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/accept-language": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/accept-language/-/accept-language-3.0.18.tgz", + "integrity": "sha1-9QJfF79lpGaoRYOMz5jNuHfYM4Q=", + "dependencies": { + "bcp47": "^1.1.2", + "stable": "^0.1.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bcp47": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz", + "integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/cldrjs": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.5.tgz", + "integrity": "sha512-KDwzwbmLIPfCgd8JERVDpQKrUUM1U4KpFJJg2IROv89rF172lLufoJnqJ/Wea6fXL5bO6WjuLMzY8V52UWPvkA==" + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.0.tgz", + "integrity": "sha512-sj9tj3z5cnHaSJCYObA9nISf7eq/YjscLPoq6nmew4SiOjxqL2KRpK20fjnjVbpNDjJ2HR3MoVcWKXwbVvzS0A==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz", + "integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-loopback": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-loopback/-/eslint-config-loopback-13.1.0.tgz", + "integrity": "sha512-Dg4IylCM5ysK9LsfzNZYLpnBjkgsBnjLMcprAMW8r7EMSody4GwOzeMixlkboNxeXZAG0z7aezh3fIJcOWFEVg==", + "dev": true, + "dependencies": { + "eslint-plugin-mocha": "^5.2.0" + } + }, + "node_modules/eslint-plugin-mocha": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-5.3.0.tgz", + "integrity": "sha512-3uwlJVLijjEmBeNyH60nzqgA1gacUWLUmcKV8PIGNvj1kwP/CTgAWQHn2ayyJVwziX+KETkr9opNwT1qD/RZ5A==", + "dev": true, + "dependencies": { + "ramda": "^0.26.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">= 4.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-utils/node_modules/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==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/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==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/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 + }, + "node_modules/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==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/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==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.1.tgz", + "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/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, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globalize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/globalize/-/globalize-1.6.0.tgz", + "integrity": "sha512-MTuAU3Tnbtga8PvxbpSPdQNIs6K5UdATWIuarWJK2Z3e1DghXpxb/GmShSVagzHqCOYgZr7N/Hi7D1mrHG30jQ==", + "dependencies": { + "cldrjs": "^0.5.4" + } + }, + "node_modules/globals": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", + "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dev": true, + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflection": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz", + "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==", + "dev": true, + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/invert-kv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz", + "integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sindresorhus/invert-kv?sponsor=1" + } + }, + "node_modules/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==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/juggler-v3": { + "resolved": "deps/juggler-v3", + "link": true + }, + "node_modules/juggler-v4": { + "resolved": "deps/juggler-v4", + "link": true + }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "node_modules/lcid": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", + "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", + "dependencies": { + "invert-kv": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/loopback-connector": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.0.1.tgz", + "integrity": "sha512-aSPT6x5WZdoW9ylyNE4CxGqFbIqC9cSEZJwWkCincso27PXlZPj52POoF6pgxug9mkH7MrbXuP3SSDLkLq5oQQ==", + "dependencies": { + "async": "^3.2.0", + "bluebird": "^3.7.2", + "debug": "^4.1.1", + "msgpack5": "^4.2.0", + "strong-globalize": "^6.0.4", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/loopback-datasource-juggler": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/loopback-datasource-juggler/-/loopback-datasource-juggler-4.26.0.tgz", + "integrity": "sha512-/R40jUGDrnRBgTh121L4Y7sHDF0KxbgSAN4gLJKp8xGNQ6KpkSQyqZkmap98eN7B75RES78DS3MGghsYMvAJ3Q==", + "dev": true, + "dependencies": { + "async": "^3.1.0", + "change-case": "^4.1.1", + "debug": "^4.1.0", + "depd": "^2.0.0", + "inflection": "^1.6.0", + "lodash": "^4.17.11", + "loopback-connector": "^5.0.0", + "minimatch": "^3.0.3", + "qs": "^6.5.0", + "shortid": "^2.2.6", + "strong-globalize": "^6.0.5", + "traverse": "^0.6.6", + "uuid": "^8.3.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/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, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/mem": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", + "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^2.1.0", + "p-is-promise": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/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 + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/msgpack5": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-4.5.1.tgz", + "integrity": "sha512-zC1vkcliryc4JGlL6OfpHumSYUHWFGimSI+OgfRCjTFLmKA2/foR9rMTOhWiqfOrfxJOctrpWPvrppf8XynJxw==", + "dependencies": { + "bl": "^2.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.3.6", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-locale": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", + "integrity": "sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==", + "dependencies": { + "execa": "^4.0.0", + "lcid": "^3.0.0", + "mem": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/pg": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", + "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.3.0", + "pg-protocol": "^1.5.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "pg-native": ">=2.0.0" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", + "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", + "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", + "dependencies": { + "split2": "^3.1.1" + } + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", + "dev": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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==", + "dependencies": { + "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" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shortid": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", + "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", + "dev": true, + "dependencies": { + "nanoid": "^2.1.0" + } + }, + "node_modules/shortid/node_modules/nanoid": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", + "dev": true + }, + "node_modules/should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "dependencies": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "node_modules/should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "dependencies": { + "should-type": "^1.4.0" + } + }, + "node_modules/should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "node_modules/should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "node_modules/should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "dependencies": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "node_modules/should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "node_modules/sinon": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/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==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/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==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strong-globalize": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-6.0.5.tgz", + "integrity": "sha512-7nfUli41TieV9/TSc0N62ve5Q4nfrpy/T0nNNy6TyD3vst79QWmeylCyd3q1gDxh8dqGEtabLNCdPQP1Iuvecw==", + "dependencies": { + "accept-language": "^3.0.18", + "debug": "^4.2.0", + "globalize": "^1.6.0", + "lodash": "^4.17.20", + "md5": "^2.3.0", + "mkdirp": "^1.0.4", + "os-locale": "^5.0.0", + "yamljs": "^0.3.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz", + "integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/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==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "dependencies": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + }, + "bin": { + "json2yaml": "bin/json2yaml", + "yaml2json": "bin/yaml2json" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/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, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.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" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "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" + } + } + } + }, + "@commitlint/config-conventional": { + "version": "12.1.4", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-12.1.4.tgz", + "integrity": "sha512-ZIdzmdy4o4WyqywMEpprRCrehjCSQrHkaRTVZV411GyLigFQHlEBSJITAihLAWe88Qy/8SyoIe5uKvAsV5vRqQ==", + "dev": true, + "requires": { + "conventional-changelog-conventionalcommits": "^4.3.1" + } + }, + "@eslint/eslintrc": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz", + "integrity": "sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + } + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "accept-language": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/accept-language/-/accept-language-3.0.18.tgz", + "integrity": "sha1-9QJfF79lpGaoRYOMz5jNuHfYM4Q=", + "requires": { + "bcp47": "^1.1.2", + "stable": "^0.1.6" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "bcp47": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz", + "integrity": "sha1-NUvjMH/9CEM6ePXh4glYRfifx/4=" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "cldrjs": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/cldrjs/-/cldrjs-0.5.5.tgz", + "integrity": "sha512-KDwzwbmLIPfCgd8JERVDpQKrUUM1U4KpFJJg2IROv89rF172lLufoJnqJ/Wea6fXL5bO6WjuLMzY8V52UWPvkA==" + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "conventional-changelog-conventionalcommits": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.0.tgz", + "integrity": "sha512-sj9tj3z5cnHaSJCYObA9nISf7eq/YjscLPoq6nmew4SiOjxqL2KRpK20fjnjVbpNDjJ2HR3MoVcWKXwbVvzS0A==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz", + "integrity": "sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-config-loopback": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-loopback/-/eslint-config-loopback-13.1.0.tgz", + "integrity": "sha512-Dg4IylCM5ysK9LsfzNZYLpnBjkgsBnjLMcprAMW8r7EMSody4GwOzeMixlkboNxeXZAG0z7aezh3fIJcOWFEVg==", + "dev": true, + "requires": { + "eslint-plugin-mocha": "^5.2.0" + } + }, + "eslint-plugin-mocha": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-5.3.0.tgz", + "integrity": "sha512-3uwlJVLijjEmBeNyH60nzqgA1gacUWLUmcKV8PIGNvj1kwP/CTgAWQHn2ayyJVwziX+KETkr9opNwT1qD/RZ5A==", + "dev": true, + "requires": { + "ramda": "^0.26.1" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "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 + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "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==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.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 + }, + "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==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "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==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.1.tgz", + "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "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 + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globalize": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/globalize/-/globalize-1.6.0.tgz", + "integrity": "sha512-MTuAU3Tnbtga8PvxbpSPdQNIs6K5UdATWIuarWJK2Z3e1DghXpxb/GmShSVagzHqCOYgZr7N/Hi7D1mrHG30jQ==", + "requires": { + "cldrjs": "^0.5.4" + } + }, + "globals": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", + "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dev": true, + "requires": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflection": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz", + "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "invert-kv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz", + "integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==" + }, + "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==", + "dev": true, + "requires": { + "binary-extensions": "^2.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==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "juggler-v3": { + "version": "file:deps/juggler-v3", + "requires": { + "loopback-datasource-juggler": "3.x", + "should": "^8.4.0" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "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" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "loopback-connector": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-4.11.1.tgz", + "integrity": "sha512-EA31zur3xIhP4UW+P2rWEcSbqpk4jPddpTBZSSw8KCszM7T0/Pe4HvEmG0MndAWJctRPtrwKDEu/8rWuMDLf+A==", + "dev": true, + "requires": { + "async": "^3.2.0", + "bluebird": "^3.7.2", + "debug": "^4.1.1", + "msgpack5": "^4.2.0", + "strong-globalize": "^5.1.0", + "uuid": "^7.0.3" + }, + "dependencies": { + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", + "dev": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "strong-globalize": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-5.1.0.tgz", + "integrity": "sha512-9cooAb6kNMDFmTDybkkch1x7b+LuzZNva8oIr+MxXnvx9jcvw4/4DTSXPc53mG68G0Q9YOTYZkhDkWe/DiJ1Qg==", + "dev": true, + "requires": { + "accept-language": "^3.0.18", + "debug": "^4.1.1", + "globalize": "^1.5.0", + "lodash": "^4.17.15", + "md5": "^2.2.1", + "mkdirp": "^0.5.5", + "os-locale": "^5.0.0", + "yamljs": "^0.3.0" + } + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "dev": true + } + } + }, + "loopback-datasource-juggler": { + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/loopback-datasource-juggler/-/loopback-datasource-juggler-3.36.1.tgz", + "integrity": "sha512-6eop3qxFyN3AkPBPUte2DHcsW1DopJwXXA20x3vwYsBSo4hLSv4gIeXo0+yqdQoXpHfbKRB9cv1hHEHAQSiWUA==", + "dev": true, + "requires": { + "async": "^2.6.0", + "bluebird": "^3.1.1", + "debug": "^3.1.0", + "depd": "^1.0.0", + "inflection": "^1.6.0", + "lodash": "^4.17.4", + "loopback-connector": "^4.4.0", + "minimatch": "^3.0.3", + "qs": "^6.5.0", + "shortid": "^2.2.6", + "strong-globalize": "^4.1.1", + "traverse": "^0.6.6", + "uuid": "^3.0.1" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "should": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/should/-/should-8.4.0.tgz", + "integrity": "sha1-XmCInT5kS73Tl6MM00+tKPz5C8A=", + "dev": true, + "requires": { + "should-equal": "0.8.0", + "should-format": "0.3.2", + "should-type": "0.2.0" + } + }, + "should-equal": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-0.8.0.tgz", + "integrity": "sha1-o/BXMv9FusG3ukEvhAiFaBlkEpk=", + "dev": true, + "requires": { + "should-type": "0.2.0" + } + }, + "should-format": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-0.3.2.tgz", + "integrity": "sha1-pZgx4Bot3uFJkRvHFIvlyAMZ4f8=", + "dev": true, + "requires": { + "should-type": "0.2.0" + } + }, + "should-type": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-0.2.0.tgz", + "integrity": "sha1-ZwfvlVKdmJ3MCY/gdTqx+RNrt/Y=", + "dev": true + }, + "strong-globalize": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-4.1.3.tgz", + "integrity": "sha512-SJegV7w5D4AodEspZJtJ7rls3fmi+Zc0PdyJCqBsg4RN9B8TC80/uAI2fikC+s1Jp9FLvr2vDX8f0Fqc62M4OA==", + "dev": true, + "requires": { + "accept-language": "^3.0.18", + "debug": "^4.1.1", + "globalize": "^1.4.2", + "lodash": "^4.17.4", + "md5": "^2.2.1", + "mkdirp": "^0.5.1", + "os-locale": "^3.1.0", + "yamljs": "^0.3.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + } + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "juggler-v4": { + "version": "file:deps/juggler-v4", + "requires": { + "loopback-datasource-juggler": "4.x", + "should": "^13.2.3" + } + }, + "just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "dev": true + }, + "lcid": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", + "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", + "requires": { + "invert-kv": "^3.0.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "loopback-connector": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/loopback-connector/-/loopback-connector-5.0.1.tgz", + "integrity": "sha512-aSPT6x5WZdoW9ylyNE4CxGqFbIqC9cSEZJwWkCincso27PXlZPj52POoF6pgxug9mkH7MrbXuP3SSDLkLq5oQQ==", + "requires": { + "async": "^3.2.0", + "bluebird": "^3.7.2", + "debug": "^4.1.1", + "msgpack5": "^4.2.0", + "strong-globalize": "^6.0.4", + "uuid": "^8.3.0" + } + }, + "loopback-datasource-juggler": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/loopback-datasource-juggler/-/loopback-datasource-juggler-4.26.0.tgz", + "integrity": "sha512-/R40jUGDrnRBgTh121L4Y7sHDF0KxbgSAN4gLJKp8xGNQ6KpkSQyqZkmap98eN7B75RES78DS3MGghsYMvAJ3Q==", + "dev": true, + "requires": { + "async": "^3.1.0", + "change-case": "^4.1.1", + "debug": "^4.1.0", + "depd": "^2.0.0", + "inflection": "^1.6.0", + "lodash": "^4.17.11", + "loopback-connector": "^5.0.0", + "minimatch": "^3.0.3", + "qs": "^6.5.0", + "shortid": "^2.2.6", + "strong-globalize": "^6.0.5", + "traverse": "^0.6.6", + "uuid": "^8.3.1" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "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" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, + "md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "mem": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", + "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^2.1.0", + "p-is-promise": "^2.1.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "requires": { + "argparse": "^2.0.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 + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "msgpack5": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-4.5.1.tgz", + "integrity": "sha512-zC1vkcliryc4JGlL6OfpHumSYUHWFGimSI+OgfRCjTFLmKA2/foR9rMTOhWiqfOrfxJOctrpWPvrppf8XynJxw==", + "requires": { + "bl": "^2.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.3.6", + "safe-buffer": "^5.1.2" + } + }, + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "os-locale": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", + "integrity": "sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==", + "requires": { + "execa": "^4.0.0", + "lcid": "^3.0.0", + "mem": "^5.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "pg": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", + "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.3.0", + "pg-protocol": "^1.5.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", + "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==", + "requires": {} + }, + "pg-protocol": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", + "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", + "requires": { + "split2": "^3.1.1" + } + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "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==", + "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" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "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 + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "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==" + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "shortid": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", + "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", + "dev": true, + "requires": { + "nanoid": "^2.1.0" + }, + "dependencies": { + "nanoid": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", + "dev": true + } + } + }, + "should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "requires": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "requires": { + "should-type": "^1.4.0" + } + }, + "should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "requires": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "requires": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "sinon": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } + } + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.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==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "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==", + "dev": true + }, + "strong-globalize": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/strong-globalize/-/strong-globalize-6.0.5.tgz", + "integrity": "sha512-7nfUli41TieV9/TSc0N62ve5Q4nfrpy/T0nNNy6TyD3vst79QWmeylCyd3q1gDxh8dqGEtabLNCdPQP1Iuvecw==", + "requires": { + "accept-language": "^3.0.18", + "debug": "^4.2.0", + "globalize": "^1.6.0", + "lodash": "^4.17.20", + "md5": "^2.3.0", + "mkdirp": "^1.0.4", + "os-locale": "^5.0.0", + "yamljs": "^0.3.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.1.tgz", + "integrity": "sha512-42VLtQUOLefAvKFAQIxIZDaThq6om/PrfP0CYk3/vn+y4BMNkKnbli8ON2QCiHov4KkzOSJ/xSoBJdayiiYvVQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.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 + }, + "workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "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 + }, + "yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "requires": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "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 + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json index 97ebaaae..da6c315b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "node": ">=10" }, "keywords": [ - "StrongLoop", "LoopBack", "PostgreSQL", "DataSource", @@ -46,11 +45,12 @@ "mocha": "^8.1.2", "rc": "^1.0.0", "should": "^13.2.3", - "sinon": "^9.0.2" + "sinon": "^9.0.2", + "@commitlint/config-conventional": "^12.1.4" }, "repository": { "type": "git", - "url": "https://github.com/strongloop/loopback-connector-postgresql.git" + "url": "https://github.com/loopbackio/loopback-connector-postgresql.git" }, "license": "Artistic-2.0", "author": "IBM Corp." From 1199248a0a3e2881241e01d970bb1411605bfead Mon Sep 17 00:00:00 2001 From: SAMI BETTAYEB Date: Thu, 17 Jun 2021 23:26:39 +0100 Subject: [PATCH 67/72] =?UTF-8?q?=E2=9C=A8=20Add=20support=20to=20query=20?= =?UTF-8?q?encrypted=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: SAMI BETTAYEB --- lib/postgresql.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/postgresql.js b/lib/postgresql.js index 2ac994f2..9292bc27 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -588,6 +588,17 @@ PostgreSQL.prototype.buildWhere = function(model, where) { return whereClause; }; +PostgreSQL.prototype.getEncryptionFields = function(modelDefinition) { + if(modelDefinition + && modelDefinition.settings + && modelDefinition.settings.mixins + && modelDefinition.settings.mixins.Encryption + && modelDefinition.settings.mixins.Encryption.fields){ + return modelDefinition.settings.mixins.Encryption.fields + } + return [] +} + /** * @private * @param model @@ -606,6 +617,7 @@ PostgreSQL.prototype._buildWhere = function(model, where) { const self = this; const props = self.getModelDefinition(model).properties; + const encryptedFields = this.getEncryptionFields(this.getModelDefinition(model)) const whereStmts = []; for (const key in where) { const stmt = new ParameterizedSQL('', []); @@ -646,7 +658,18 @@ PostgreSQL.prototype._buildWhere = function(model, where) { } // eslint-disable one-var let expression = where[key]; - const columnName = self.columnEscaped(model, key); + let columnName = self.columnEscaped(model, key); + if(encryptedFields.includes(key)){ + columnName = `convert_from( + decrypt_iv( + DECODE(${key},'hex')::bytea, + decode('${process.env.ENCRYPTION_HEX_KEY}','hex')::bytea, + decode('${process.env.ENCRYPTION_HEX_IV}','hex')::bytea, + 'aes' + ), + 'utf8' + )` + } // eslint-enable one-var if (expression === null || expression === undefined) { stmt.merge(columnName + ' IS NULL'); From 8899f593c18472223c935ec5dced39711944f665 Mon Sep 17 00:00:00 2001 From: SAMI BETTAYEB Date: Tue, 22 Jun 2021 21:45:11 +0100 Subject: [PATCH 68/72] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Add=20dev=20dependen?= =?UTF-8?q?cies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: SAMI BETTAYEB --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index da6c315b..effabaa6 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,8 @@ }, "devDependencies": { "eslint": "^7.7.0", + "chai": "^4.3.4", + "chai-subset": "^1.6.0", "eslint-config-loopback": "^13.1.0", "juggler-v3": "file:./deps/juggler-v3", "juggler-v4": "file:./deps/juggler-v4", From c1a20749bddfebd43391fdc02af38c0797422292 Mon Sep 17 00:00:00 2001 From: SAMI BETTAYEB Date: Tue, 22 Jun 2021 21:47:42 +0100 Subject: [PATCH 69/72] =?UTF-8?q?=F0=9F=97=83=20Enable=20pgcrypto=20extens?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: SAMI BETTAYEB --- lib/migration.js | 3 ++- lib/postgresql.js | 27 ++++++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/migration.js b/lib/migration.js index 57ad4310..d20f6888 100644 --- a/lib/migration.js +++ b/lib/migration.js @@ -351,7 +351,8 @@ function mixinMigration(PostgreSQL) { }); // default extension if (!createExtensions) { - createExtensions = 'CREATE EXTENSION IF NOT EXISTS "uuid-ossp";'; + createExtensions = `CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + CREATE EXTENSION IF NOT EXISTS "pgcrypto";`; } // Please note IF NOT EXISTS is introduced in postgresql v9.3 diff --git a/lib/postgresql.js b/lib/postgresql.js index 9292bc27..84086977 100644 --- a/lib/postgresql.js +++ b/lib/postgresql.js @@ -112,6 +112,7 @@ PostgreSQL.prototype.connect = function(callback) { self.client = client; process.nextTick(releaseCb); callback && callback(err, client); + if (!err) self.execute('CREATE EXTENSION IF NOT EXISTS pgcrypto', function(createExtensionError) {}); }); }; @@ -589,15 +590,15 @@ PostgreSQL.prototype.buildWhere = function(model, where) { }; PostgreSQL.prototype.getEncryptionFields = function(modelDefinition) { - if(modelDefinition - && modelDefinition.settings - && modelDefinition.settings.mixins - && modelDefinition.settings.mixins.Encryption - && modelDefinition.settings.mixins.Encryption.fields){ - return modelDefinition.settings.mixins.Encryption.fields - } - return [] -} + if (modelDefinition + && modelDefinition.settings + && modelDefinition.settings.mixins + && modelDefinition.settings.mixins.Encryption + && modelDefinition.settings.mixins.Encryption.fields) { + return modelDefinition.settings.mixins.Encryption.fields; + } + return []; +}; /** * @private @@ -617,7 +618,7 @@ PostgreSQL.prototype._buildWhere = function(model, where) { const self = this; const props = self.getModelDefinition(model).properties; - const encryptedFields = this.getEncryptionFields(this.getModelDefinition(model)) + const encryptedFields = this.getEncryptionFields(this.getModelDefinition(model)); const whereStmts = []; for (const key in where) { const stmt = new ParameterizedSQL('', []); @@ -659,16 +660,16 @@ PostgreSQL.prototype._buildWhere = function(model, where) { // eslint-disable one-var let expression = where[key]; let columnName = self.columnEscaped(model, key); - if(encryptedFields.includes(key)){ + if (encryptedFields.includes(key)) { columnName = `convert_from( decrypt_iv( DECODE(${key},'hex')::bytea, decode('${process.env.ENCRYPTION_HEX_KEY}','hex')::bytea, - decode('${process.env.ENCRYPTION_HEX_IV}','hex')::bytea, + decode('${process.env.ENCRYPTION_HEX_IV}','hex')::bytea, 'aes' ), 'utf8' - )` + )`; } // eslint-enable one-var if (expression === null || expression === undefined) { From 81dfaecdf5a326ee56dfbbb0e8a66d715a833c6c Mon Sep 17 00:00:00 2001 From: SAMI BETTAYEB Date: Tue, 22 Jun 2021 21:50:47 +0100 Subject: [PATCH 70/72] =?UTF-8?q?=F0=9F=94=A7=20Add=20required=20crypto=20?= =?UTF-8?q?env=20variables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: SAMI BETTAYEB --- test/init.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/init.js b/test/init.js index d2fa8feb..514c5fa0 100644 --- a/test/init.js +++ b/test/init.js @@ -21,6 +21,9 @@ process.env.PGUSER = process.env.POSTGRESQL_USER || process.env.PGPASSWORD = process.env.POSTGRESQL_PASSWORD || process.env.PGPASSWORD || ''; +process.env.ENCRYPTION_HEX_KEY = process.env.ENCRYPTION_HEX_KEY || 'abcdef0123456789abcdef0123456789'; +process.env.ENCRYPTION_HEX_IV = process.env.ENCRYPTION_HEX_IV || '0123456789abcdef0123456789abcdef'; + config = { host: process.env.PGHOST, port: process.env.PGPORT, From b4ff5e71d8c2fd7e2992915958194f6ca83e8640 Mon Sep 17 00:00:00 2001 From: SAMI BETTAYEB Date: Tue, 22 Jun 2021 21:51:47 +0100 Subject: [PATCH 71/72] =?UTF-8?q?=E2=9C=85=20=F0=9F=97=83=20Add=20encrypte?= =?UTF-8?q?d=5Fdata=20table=20for=20testing=20purposes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: SAMI BETTAYEB --- test/schema.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/schema.sql b/test/schema.sql index 7020812c..cd59447b 100644 --- a/test/schema.sql +++ b/test/schema.sql @@ -377,6 +377,16 @@ CREATE TABLE reservation ( ); +-- +-- Name: encrypted_data; Type: TABLE; Schema: strongloop; Owner: strongloop +-- + +CREATE TABLE encrypted_data ( + id character varying(64), + data text +); + + -- -- Name: session; Type: TABLE; Schema: strongloop; Owner: strongloop -- @@ -1207,6 +1217,8 @@ INSERT INTO product VALUES ('87', 'NV Goggles', NULL, NULL, NULL, NULL, NULL); INSERT INTO product VALUES ('2', 'G17', 53, 75, 15, 'Flashlight', 'Single'); INSERT INTO product VALUES ('5', 'M9 SD', 0, 75, 15, 'Silenced', 'Single'); +INSERT INTO encrypted_data VALUES('1', '1c93722e6cf53f93dd4eb15a18444dc3e910fded18239db612794059af1fa5e8'); + -- -- Data for Name: reservation; Type: TABLE DATA; Schema: strongloop; Owner: strongloop From 9beef0c353f335731e498fe262f6daac50012103 Mon Sep 17 00:00:00 2001 From: SAMI BETTAYEB Date: Tue, 22 Jun 2021 21:53:08 +0100 Subject: [PATCH 72/72] =?UTF-8?q?=E2=9C=A8=20=E2=9C=85=20Add=20encrypted?= =?UTF-8?q?=20data=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: SAMI BETTAYEB --- test/postgresql.encrypted.test.js | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 test/postgresql.encrypted.test.js diff --git a/test/postgresql.encrypted.test.js b/test/postgresql.encrypted.test.js new file mode 100644 index 00000000..4dd7e5cd --- /dev/null +++ b/test/postgresql.encrypted.test.js @@ -0,0 +1,79 @@ +// Copyright IBM Corp. 2014,2019. All Rights Reserved. +// Node module: loopback-connector-postgresql +// This file is licensed under the Artistic License 2.0. +// License text available at https://opensource.org/licenses/Artistic-2.0 + +'use strict'; +process.env.NODE_ENV = 'test'; +require('should'); +const expect = require('chai').expect; +const async = require('async'); +const chai = require('chai'); +const chaiSubset = require('chai-subset'); +chai.use(chaiSubset); + +let db; + +before(function() { + db = global.getSchema(); +}); + +describe('Mapping models', function() { + it('should return encrypted data by filter', function(done) { + const schema = + { + 'name': 'EncryptedData', + 'options': { + 'idInjection': false, + 'postgresql': { + 'schema': 'public', 'table': 'encrypted_data', + }, + }, + 'properties': { + 'id': { + 'type': 'String', + 'id': true, + }, + 'data': { + 'type': 'String', + }, + }, + 'mixins': { + 'Encryption': { + 'fields': [ + 'data', + ], + }, + }, + }; + + const EncryptedData = db.createModel(schema.name, schema.properties, schema.options); + EncryptedData.settings.mixins = schema.mixins; + + db.automigrate('EncryptedData', function(err) { + if (err) console.error({err}); + EncryptedData.create({ + id: '2', + data: '1c93722e6cf53f93dd4eb15a18444dc3e910fded18239db612794059af1fa5e8', + }, function(err, encryptedData) { + if (err) console.log({err2: err}); + async.series([ + function(callback) { + EncryptedData.findOne({where: {data: {ilike: '%test%'}}}, function(err, retreivedData) { + if (err) console.error({err111: err}); + expect(retreivedData).to.containSubset(encryptedData); + callback(null, retreivedData); + }); + }, + function(callback) { + EncryptedData.find({where: {data: {ilike: '%not found%'}}}, function(err, retreivedData) { + if (err) console.error({err111: err}); + expect(retreivedData.length).to.equal(0); + callback(null, retreivedData); + }); + }, + ], done); + }); + }); + }); +});