diff --git a/.travis.yml b/.travis.yml index 751e129..5964cd0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,10 @@ cache: directories: - "$HOME/.npm" - node_modules +services: + - postgresql +before_script: + - psql -c 'create database test;' -U postgres install: - "npm install" script: diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md new file mode 100644 index 0000000..95d8bc8 --- /dev/null +++ b/DOCUMENTATION.md @@ -0,0 +1,448 @@ +# [postgresql-client](https://github.com/panates/postgresql-client) + +# Contents + +- 1\. [Usage](#1-usage) + - 1.1 [Connecting](#1-1-connecting) + - 1.1.1 [Connection strings](#1-1-1-connection-strings) + - 1.1.2 [Environment variables](#1-1-2-environmentvariables) + - 1.2 [Pooling](#12pooling) + - 1.2.1 [Pool configuration](#1-2-1-poolcon-figuration) + - 1.2.2 [Obtaining a connection](#1-2-2-obtaining-a-connection) + - 1.2.3 [Shutting down the pool](#1-2-3-shutting-down-the-pool) + - 1.3 [Queries](#1-3-queries) + - 1.3.1 [Simple query](#1-3-1-simple-query) + - 1.3.2 [Extended query](#1-3-2-simple-query) + - 1.3.3 [Prepared Statements](#1-3-3-prepared-statements) + - 1.3.4 [Using Cursors](#1-3-4-using-cursors) + - 1.4 [Transactions](#1-4-transactions) + - 1.5 [Registering data types](#1-5-registering-datatypes) +- 2\. [API](#2-api) + - 2.1 [Classes](#2-1-classes) + - 2.1.1 [Connection](#2-1-1-connection) + - 2.1.2 [Pool](#2-1-2-pool) + - 2.1.3 [Cursor](#2-1-3-cursor) + - 2.1.4 [PreparedStatement](#2-1-4-prepared-statement) + - 2.1.5 [ScriptExecutor](#2-1-5-script-executor) + - 2.1.6 [BindParam](#2-1-6-bindparam) + - 2.1.7 [DataTypeMap](#2-1-7-datatypemap) + - 2.2 [Interfaces](#2-2-interfaces) + - 2.2.1 [ConnectionConfiguration](#2-2-1-connection-configuration) + - 2.2.2 [PoolConfiguration](#2-2-2-pool-configuration) + - 2.2.3 [DataMappingOptions](#2-2-3-datamappingoptions) + - 2.2.4 [ScriptExecuteOptions](#2-2-4-scriptexecuteoptions) + - 2.2.5 [ScriptResult](#2-2-5-scriptresult) + - 2.2.6 [CommandResult](#2-2-6-commandresult) + - 2.2.7 [FieldInfo](#2-2-7-fieldinfo) + - 2.2.8 [StatementPrepareOptions](#2-2-8-statementprepareoptions) + - 2.2.9 [QueryOptions](#2-2-9-queryoptions) + - 2.2.10 [QueryResult](#2-2-10-queryresult) + +# 1. Usage + +## 1.1. Connecting +The library supports both single and pooled connections. +If you want to establish a single session to a PostgreSQL server +you need to use `Connection` class. If you require a connection pool use `Pool` class instead. + + +*new Connection([config: String | [ConnectionConfiguration](#2-2-1-connectionconfiguration)]);* + +```ts +import {Connection} from 'postgresql-client'; + +const connection = new Connection({ + host: 'localhost', + port: 5432, + user: 'user1', + password: 'mypass', + database: 'mydb', + timezone: 'Europe/Amsterdam' +}); +await connection.connect(); +// Do whatever you need with connection +await conection.close(); +``` + +### 1.1.1. Connection Strings +You can initialize both a `Connection` and `Pool` using a connection string uri. +Unix domain sockets and TCP uri's can be used as connection string. + +#### UNIX domain socket + +`[unix:// | socket://][][:]@[?query&query...]` + +`/var/run/pgsql` + +`/var/run/pgsql?db=mydb` + +`unix:///var/run/pgsql` + +`socket:/var/run/pgsql` + +`socket://user:pass@/var/run/pgsql` + +`socket://user:pass@/var/run/pgsql?db=mydb` + +```ts +const connection = new Connection('postgres://someuser:somepassword@somehost:381/somedatabase'); +``` + +#### TCP connection URI + +`[pg:// | postgres://][][:]@[:][/][?query&query...]` + +`pg://user:pass@localhost:5432/mydb` + +`pg://localhost?db=mydb&user=me` + + +### 1.1.2. Environment variables +Configuration object and connection strings are optional for both `Connection` and `Pool` classes. +If no argument given while creating an instance, +same [environment variables](https://www.postgresql.org/docs/9.1/libpq-envars.html) as libpq will be used to establish connection. + +Current supported environment variables are [PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD, PGAPPNAME, PGTZ, PGCONNECT_TIMEOUT, PGSEARCHPATH] + +```ts +const connection = new Connection(); // Initialize using environment variables +``` + + + +## 1.2. Pooling +`Pool` class is used to create a connection pool. Constructor accepts connection string or [PoolConfiguration](#2-2-2-poolconfiguration) interface + +*new Pool([config: String | [PoolConfiguration](#2-2-2-poolconfiguration)]);* + +```ts +import {Pool} from 'postgresql-client'; + +const dbpool = new Pool({ + host: 'postgres://localhost', + pool: { + min: 1, + max: 10, + idleTimeoutMillis: 5000 + } +}); +const qr = await pool.query('select * from my_table where id=1'); +// Do whatever you need with pool +await dbpool.close(); // Disconnect all connections and shutdown pool +``` + +### 1.2.2. Obtaining a connection + +The pool returns an idle `Connection` instance when you call `pool.acquire()` function. +You must call `connection.release()` method when you done with the connection. + +`pool.acquire(): Promise;` + +```ts + const connection = await dbpool.acquire(); + try { + const qr = await connection.query('select * from my_table where id=1'); + // ... Do whatever you need with connection + } finally { + await connection.release(); // Connection will go back to the pool + } +``` + +`Pool` class has `pool.execute()` and `pool.query()` methods which applies "obtain a connection", +"execute the given query" and "release the connection" sequence. +This is the comfortable and secure way +if you don't execute your query in a transaction. +So you don't need to take care of releasing the connection +every time. + +### 1.2.3. Shutting down the pool +To shut down a pool call `pool.close()` method. +This will wait for active connections to get idle than will release all resources. +If you define `terminateWait argument, the pool wait until the given period of time in ms, before force connections to close. + +`pool.close(terminateWait?: number): Promise;` + + +## 1.3. Queries + +### 1.3.1 Simple query +PostgreSQL wire protocol has two kind of way to execute SQL scripts. +Simple query is the mature way. +Simple query supports executing more than one sql scripts in a single command. +But it does not support *bind parameters* and server transfers data in text format which is slower than binary format. +So it may cause performance and security problems. +We suggest to use `query()` method which uses *Extended query protocol* if you need bind parameters or need to return rows. + +To execute SQL scripts you can create a `ScriptExecutor` instance or just call `connection.execute()` or `pool.execute()` methods. + +*pool.execute(sql: string, options?: [ScriptExecuteOptions](#2-2-4-scriptexecuteOptions)]): Promise\<[ScriptResult](#225scriptresult)>;* + +*connection.execute(sql: string, options?: [ScriptExecuteOptions](#2-2-4-scriptexecuteOptions)]): Promise\<[ScriptResult](#225scriptresult)>;* + +```ts +const qr = await connection.execute('BEGIN; update my_table set ref = ref+1; END;'); +console.log(qr.results[1].rowsAffected + ' rows updated'); +``` + +```ts +const scriptExecutor = new ScriptExecutor(connection); +scriptExecutor.on('start', ()=>console.log('Script execution started')); +scriptExecutor.on('command-complete', (cmd) => console.log(cmd.command + ' complete')); +scriptExecutor.on('row', (row)=>console.log('Row received: ', row)); +scriptExecutor.on('finish', ()=>console.log('Script execution complete')); +await scriptExecutor.execute(` + BEGIN; + update my_table set ref = ref+1; + select * from my_table where id=1; + END;`); +``` + + + + +## 1.3.2. Extended query + +In the extended-query protocol, *prepared statements* and *portals* are used. +Unlike simple query, extended query protocol supports parameter binding and binary data format. +The only limit is you can execute one command at a time. + +*pool.query(sql: string, options?: [QueryOptions](#2-2-9-queryoptions)]): Promise\<[QueryResult](#2210queryresult)>;* + +*connection.query(sql: string, options?: [QueryOptions](#2-2-9-queryoptions)]): Promise\<[QueryResult](#2210queryresult)>;* + + +```ts +const qr = await connection.query('select * from my_table'); +console.log(qr.fields); +console.log(qr.rows); +``` + + + + +## 1.3.3. Prepared Statements + +Prepared statements are great when you need executing a script more than once (etc. bulk insert or update). +It dramatically reduces execution time. + +To create a [PreparedStatement](#2-1-4-preparedstatement) instance or just call `connection.prepare()` or `pool.prepare()` methods. + +*pool.prepare(sql: string, options?: [StatementPrepareOptions](#2-2-8-statementprepareoptions)]): Promise\<[PreparedStatement](#214preparedstatement)>;* + +*connection.prepare(sql: string, options?: [StatementPrepareOptions](#2-2-8-statementprepareoptions)]): Promise\<[PreparedStatement](#214preparedstatement)>;* + +```ts +import {DataTypeOIDs} from 'postgresql-client'; + +// ..... +const statement = await connection.prepare( + 'insert into my_table(id, name) values ($1, $2)', { + paramTypes: [DataTypeOIDs.Int4, DataTypeOIDs.Varchar] + }); + +for (let i = 0; i < 100; i++) { + await statement.execute({params: [i, ('name' + i)]}); +} +await statement.close(); // When you done, close the statement to relase resources +``` + + + +## 1.3.4. Using Cursors + + +```ts +const qr = await connection.query('select * from my_table', {cursor: true}); +console.log(qr.fields); +const cursor = qr.cursor; +let row; +while ((row = cursor.next())) { + console.log(row); +} +await cursor.close(); // When you done, close the cursor to relase resources +``` + + +# 2. API + +## 2.1. Classes + + +### 2.1.1. Connection + +*new Connection([config: String | [ConnectionConfiguration](#2-2-1-connectionconfiguration)]);* + +#### Properties + +| Key | Type | Readonly | Description | +|-----------------|:----------------------| ---------------------------------------|--------------------| +| state | `ConnectionState` | true | Returns current state of the connection | + +#### Prototype Methods + +*** +connect()*: Promise\ + + +*** +close(terminateWait?: number)*: Promise\ + + +*** +execute(sql: string, options?: [ScriptExecuteOptions](#2-2-4-scriptexecuteOptions)]): Promise\<[ScriptResult](#225scriptresult)>; + + +*** +query(sql: string, options?: [QueryOptions](#2-2-9-queryoptions)]): Promise\<[QueryResult](#2210queryresult)>; + +*** +prepare(sql: string, options?: [StatementPrepareOptions](#2-2-8-statementprepareoptions)]): Promise\<[PreparedStatement](#214preparedstatement)>; + + +#### Events + +* error +* close +* connecting +* ready +* terminate + + + + +### 2.1.2. Pool + +*new Pool([config: String | [PoolConfiguration](#2-2-2-poolconfiguration)]);* + + + + +### 2.1.3. Cursor + + +### 2.1.4. PreparedStatement + + +### 2.1.5. ScriptExecutor + + +### 2.1.6. BindParam + + +### 2.1.7. DataTypeMap + + + +## 2.2. Interfaces + +### 2.2.1. ConnectionConfiguration + +| Key | Type | Default | Description | +|-----------------|:----------------------| ---------------------------------------|--------------------| +| host | `string` | localhost | Host name or the address of the server | +| port | `number` | 5432 | Server listening port number | +| user | `string` | postgres | Authenticating user name | +| password | `string` | | User password | +| database | `string` | | Database name to be connected | +| applicationName | `string` | | The name of your application to attach with your session | +| typesMap | `DataTypeMap` | *GlobalTypeMap* |Data type map instance | +| ssl | `tls.ConnectionOptions| | SSL configuration | +| timezone | `string` | | Timezone to be set on start. (Equivalent to SET timezone TO ....) | +| searchPath | `string` | | Search path to be set on start. (Equivalent to SET search_path = ....) | +| connectTimeoutMs| `number` | 30000 | Connection timeout value in millis | +| keepAlive | `boolean` | true | Socket keep alive value | + + +### 2.2.2. PoolConfiguration + +Extends [ConnectionConfiguration](#2-2-1-connectionconfiguration) + +| Key | Type | Default | Description | +|-------------------|-------------| --------|-----------------------| +| acquireMaxRetries | `number` | 0 | Maximum number that Pool will try to create a connection before returning the error | +| acquireRetryWait | `number` | 2000 | Time in millis that Pool will wait after each tries | +| acquireTimeoutMillis | `number` | 0 | Time in millis an acquire call will wait for a connection before timing out | +| fifo | `boolean` | true | Specifies if resources will be allocated first-in-first-out order | +| idleTimeoutMillis | `number` | 30000 | The minimum amount of time in millis that a connection may sit idle in the Pool | +| houseKeepInterval | `number` | 1000 | Time period in millis that Pool will make a cleanup | +| min | `number` | 0 | Minimum number of connections that Pool will keep | +| minIdle | `number` | 0 | Minimum number of connections that Pool will keep in idle state | +| max | `number` | 10 | Maximum number of connections that Pool will create | +| maxQueue | `number` | 1000 | Maximum number of request that Pool will accept | +| validation | `boolean` | false | If true Pool test connection on acquire | + + +### 2.2.3. DataMappingOptions + +| Key | Type | Default | Description | +|--------------|-------------| --------|-----------------------| +| utcDates | `boolean` | false | If true UTC time will be used for date decoding, else system time offset will be used | + + +### 2.2.4. ScriptExecuteOptions + +Extends [DataMappingOptions](#223DataMappingOptions) + +| Key | Type | Default | Description | +|--------------|-------------| --------|-----------------------| +| objectRows | `boolean` | false | Specifies if rows will be fetched as pair objects or array of values | +| typeMap | `DataTypeMap`| *GlobalTypeMap* |Data type map instance | + + +### 2.2.5. ScriptResult + +| Key | Type | Description | +|--------------|-------------| -------------------| +| results | `CommandResult[]` | Array of command result for each sql command in the script | +| totalCommands| `number` | Command count in the script | +| totalTime | `number` | Total execution time | + + +### 2.2.6. CommandResult +| Key | Type | Description | +|--------------|--------------| -------------------| +| command | `string` | Name of the command (INSERT, SELECT, UPDATE, etc.) | +| fields | `FieldInfo[]`| Contains information about fields in column order | +| rows | `array` | Contains array of row data | +| executeTime | `number` | Time elapsed to execute command | +| rowsAffected | `number` | How many rows affected | + + +### 2.2.7. FieldInfo +| Key | Type | Description | +|--------------|-------------| -------------------| +| fieldName | `string` | Name of the field | +| tableId | `number` | OID of the table | +| columnId | `number` | OID of the column | +| dataTypeId | `number` | OID of the data type | +| fixedSize | `number` | Data length if data type has a fixed size | +| modifier | `number` | Modifier of the data type | +| isArray | `boolean`| Whether the data type is an array | + +### 2.2.8. StatementPrepareOptions + +| Key | Type | Default | Description | +|--------------|-------------| --------|-----------------------| +| paramTypes | `number[]` | | Specifies data type for each parameter | +| typeMap | `DataTypeMap` | *GlobalTypeMap* | Data type map instance | + +### 2.2.9. QueryOptions + +Extends [DataMappingOptions](#223datamappingoptions) + +| Key | Type | Default | Description | +|--------------|--------------| --------|-----------------------| +| objectRows | `boolean` | false | Specifies if rows will be fetched as pair objects or array of values | +| typeMap | `DataTypeMap`| *GlobalTypeMap* |Data type map instance | +| cursor | `boolean` | false | If true, returns Cursor instance instead of rows | +| params | `(BindParam | any)[]` | Query execution parameters | +| columnFormat | `DataFormat` `DataFormat[]`| 1 (binary) | Specifies transfer format (binary or text) for each column | +| fetchCount | `number` | 100 | Specifies how many rows will be fetched. For Cursor, this value specifies how many rows will be fetched in a batch | + +### 2.2.10. QueryResult + +Extends [CommandResult](#226commandresult) + +| Key | Type | Default | Description | +|--------------|--------------| --------|-----------------------| +| cursor | `Cursor` | | Cursor instance | diff --git a/README.md b/README.md new file mode 100644 index 0000000..af8af48 --- /dev/null +++ b/README.md @@ -0,0 +1,110 @@ +## postgresql-client + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +[![Dependencies][dependencies-image]][dependencies-url] +[![DevDependencies][devdependencies-image]][devdependencies-url] +[![Package Quality][quality-image]][quality-url] + + +Professional PostgreSQL client written in TypeScript. + + +```ts +import {Connection} from 'postgresql-client'; + +const connection = new Connection('postgres://localhost'); + +const result = await connection.query( + 'select * from cities where name like $1', + {values: ['%york%']}); +const rows = result.rows; +await connection.close(); // Disconnect +``` + +```ts +import {Pool} from 'postgresql-client'; + +const db = new Pool({ + host: 'postgres://localhost', + pool: { + min: 1, + max: 10, + idleTimeoutMillis: 5000 + } +}); + +const result = await db.query( + 'select * from cities where name like $1', + {values: ['%york%'], cursor: true}); +const cursor = result.cursor; +let row; +while ((row = cursor.next())) { + console.log(row); +} + +await db.close(); // Disconnect all connections and shutdown pool +``` + +## Features + +- Pure JavaScript library completely written in TypeScript +- Supports both single connection and pooling +- Supports named Prepared Statements +- Extended cursor support with fast double-link cache +- Extensible data-types and type mapping +- Extended bind parameter support +- Fast array support with binary encoding/decoding +- Low memory utilization and boosted performance with Shared Buffers +- Full binary wire protocol support for all data types +- Already supports text wire protocol +- Built-in ScriptExecutor which allows executing multiple scripts at once +- Asynchronous Promise based api +- Strictly typed +- Can return both array and object rows + + +## Roadmap +- Support multiple active cursors + +## Installation + +```bash +$ npm install postgresql-client --save +``` + +## Documentation +Documentation for detailed usage is [here](DOCUMENTATION.md) + +## Support +You can report bugs and discuss features on the [GitHub issues](https://github.com/panates/postgresql-client/issues) page +When you open an issue please provide version of NodeJS, PostgreSQL server an + + +## Node Compatibility + +- node >= 10.x + + +### License +postgresql-client is available under [MIT](LICENSE) license. + +[npm-image]: https://img.shields.io/npm/v/postgresql-client.svg +[npm-url]: https://npmjs.org/package/postgresql-client +[travis-image]: https://img.shields.io/travis/panates/postgresql-client/master.svg +[travis-url]: https://travis-ci.org/panates/postgresql-client +[coveralls-image]: https://img.shields.io/coveralls/panates/postgresql-client/master.svg +[coveralls-url]: https://coveralls.io/r/panates/postgresql-client +[downloads-image]: https://img.shields.io/npm/dm/postgresql-client.svg +[downloads-url]: https://npmjs.org/package/postgresql-client +[gitter-image]: https://badges.gitter.im/panates/postgresql-client.svg +[gitter-url]: https://gitter.im/panates/postgresql-client?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge +[dependencies-image]: https://david-dm.org/panates/postgresql-client/status.svg +[dependencies-url]:https://david-dm.org/panates/postgresql-client +[devdependencies-image]: https://david-dm.org/panates/postgresql-client/dev-status.svg +[devdependencies-url]:https://david-dm.org/panates/postgresql-client?type=dev +[quality-image]: http://npm.packagequality.com/shield/postgresql-client.png +[quality-url]: http://packagequality.com/#?package=postgresql-client diff --git a/package-lock.json b/package-lock.json index 576f120..e64ce2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "postgre", + "name": "postgresql-client", "version": "0.0.1", "lockfileVersion": 1, "requires": true, @@ -494,6 +494,14 @@ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", @@ -509,6 +517,11 @@ "color-convert": "^1.9.0" } }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -519,6 +532,14 @@ "picomatch": "^2.0.4" } }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "requires": { + "buffer-equal": "^1.0.0" + } + }, "append-transform": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", @@ -531,8 +552,7 @@ "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" }, "arg": { "version": "4.1.3", @@ -549,12 +569,106 @@ "sprintf-js": "~1.0.2" } }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, "array.prototype.map": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", @@ -573,12 +687,46 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "requires": { + "async-done": "^1.2.2" + } + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, "babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -601,11 +749,76 @@ } } }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } }, "big.js": { "version": "5.2.2", @@ -619,11 +832,19 @@ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -644,11 +865,31 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } }, "caching-transform": { "version": "4.0.0", @@ -701,6 +942,27 @@ "readdirp": "~3.4.0" } }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -735,6 +997,55 @@ } } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -750,6 +1061,11 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -768,17 +1084,31 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } }, "convert-source-map": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, "requires": { "safe-buffer": "~5.1.1" }, @@ -786,16 +1116,28 @@ "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==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.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=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cross-spawn": { "version": "7.0.3", @@ -808,6 +1150,15 @@ "which": "^2.0.1" } }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "debug": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", @@ -820,8 +1171,12 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "deep-is": { "version": "0.1.3", @@ -829,6 +1184,21 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, "default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -838,6 +1208,11 @@ "strip-bom": "^4.0.0" } }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=" + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -846,6 +1221,48 @@ "object-keys": "^1.0.12" } }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -870,11 +1287,37 @@ "esutils": "^2.0.2" } }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "dev": true + }, "doublylinked": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/doublylinked/-/doublylinked-2.4.0.tgz", "integrity": "sha512-wV+yfZY0P8oYoyNiQISewCBd2+kCD1cmAw8gp5WyUbpMnFwXMXjcVbdMyUgSVd+ugaeVkBYoIb9F0sP+XKiSsw==" }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -887,6 +1330,14 @@ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "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" + } + }, "enhanced-resolve": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", @@ -916,6 +1367,23 @@ "prr": "~1.0.1" } }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "errorex": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/errorex/-/errorex-2.3.2.tgz", + "integrity": "sha512-CHhTyQOi/5azvHTf2gjyYPt/HkiZ5ImJx/t6PtRV/BfiWDLa6u/Sr9HmgtgJvjfEVBxQsA/VMqIwSsQ0aGGidg==", + "requires": { + "putil-merge": "^3.2.0", + "stackframe": "^1.0.4" + } + }, "es-abstract": { "version": "1.17.7", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", @@ -1018,12 +1486,52 @@ "is-symbol": "^1.0.2" } }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, "es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1251,35 +1759,197 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } }, - "fast-glob": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", - "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", - "dev": true, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" + "homedir-polyfill": "^1.0.1" } }, - "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 + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" + } + } }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.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-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "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 }, @@ -1301,6 +1971,12 @@ "flat-cache": "^2.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1331,6 +2007,136 @@ "path-exists": "^4.0.0" } }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" + }, "flat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", @@ -1357,6 +2163,28 @@ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + }, "foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -1367,17 +2195,33 @@ "signal-exit": "^3.0.2" } }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, "fromentries": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==", "dev": true }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.1.3", @@ -1415,11 +2259,15 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1438,6 +2286,280 @@ "is-glob": "^4.0.1" } }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -1458,11 +2580,18 @@ "slash": "^3.0.0" } }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "requires": { + "sparkles": "^1.0.0" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, "growl": { "version": "1.10.5", @@ -1470,6 +2599,164 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "5.0.0-security.0" + } + }, + "yargs-parser": { + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "requires": { + "glogg": "^1.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1489,6 +2776,58 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -1505,6 +2844,19 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" + }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -1543,7 +2895,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -1552,8 +2903,54 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } }, "is-arguments": { "version": "1.0.4", @@ -1561,6 +2958,11 @@ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1581,16 +2983,60 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, "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 + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -1602,7 +3048,6 @@ "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" } @@ -1613,6 +3058,11 @@ "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", "dev": true }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=" + }, "is-negative-zero": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", @@ -1630,12 +3080,28 @@ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, "is-regex": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" } }, "is-set": { @@ -1670,11 +3136,28 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=" + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "isarray": { "version": "2.0.5", @@ -1685,8 +3168,12 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "istanbul-lib-coverage": { "version": "3.0.0", @@ -1853,8 +3340,7 @@ "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 + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "json5": { "version": "2.1.3", @@ -1865,6 +3351,49 @@ "minimist": "^1.2.5" } }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "requires": { + "flush-write-stream": "^1.0.2" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -1875,6 +3404,53 @@ "type-check": "~0.4.0" } }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "lightning-pool": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/lightning-pool/-/lightning-pool-2.3.0.tgz", + "integrity": "sha512-OSDdKc7a+kaNu+He1aoT+3FRhkOnQufuNL+xkP3RktN70cf7rd9DVg+2qOXoBvhw8Q2rOVNZxQaGl5Suar7few==", + "requires": { + "doublylinked": "^2.3.0", + "errorex": "^2.3.2", + "putil-promisify": "^1.7.2" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, "loader-utils": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", @@ -2001,6 +3577,159 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "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-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, "memory-fs": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", @@ -2031,7 +3760,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2042,6 +3770,25 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -2128,12 +3875,46 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==" + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, "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 }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, "node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -2143,11 +3924,36 @@ "process-on-spawn": "^1.0.0" } }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, "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 + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "requires": { + "once": "^1.3.2" + } }, "npm-run-path": { "version": "4.0.1", @@ -2158,6 +3964,11 @@ "path-key": "^3.0.0" } }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, "nyc": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", @@ -2345,6 +4156,39 @@ } } }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "object-inspect": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", @@ -2355,11 +4199,18 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, "object.assign": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -2367,6 +4218,43 @@ "object-keys": "^1.0.11" } }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -2376,7 +4264,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -2395,6 +4282,22 @@ "word-wrap": "^1.2.3" } }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "requires": { + "readable-stream": "^2.0.1" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, "p-limit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", @@ -2449,6 +4352,44 @@ "callsites": "^3.0.0" } }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2458,8 +4399,7 @@ "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=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "3.1.1", @@ -2470,8 +4410,20 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" }, "path-type": { "version": "4.0.0", @@ -2485,6 +4437,24 @@ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -2533,10 +4503,10 @@ } } }, - "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==" + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postgres-bytea": { "version": "3.0.0", @@ -2552,11 +4522,15 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" + }, "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==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "process-on-spawn": { "version": "1.0.0", @@ -2592,12 +4566,41 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, "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 }, + "putil-merge": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/putil-merge/-/putil-merge-3.6.2.tgz", + "integrity": "sha512-BOEhul1cp39lMFHhXtXZ7A8aVn3NhhckAcDDxGPKxpIagxtTg6Jc2eeAWZrkUC2vhZwUmKr6E8ZgpcecqJMVTQ==" + }, + "putil-promisify": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/putil-promisify/-/putil-promisify-1.7.2.tgz", + "integrity": "sha512-SFEHPZTgJOEA4yIrrQKi4x1RXy28HhXy3TDbLMdHFCshVAjRLMy2im1YjqFf8jTfeWKFyRtoYEI2Idy1GbixUA==" + }, "putil-taskqueue": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/putil-taskqueue/-/putil-taskqueue-2.5.1.tgz", @@ -2606,6 +4609,11 @@ "doublylinked": "^2.4.0" } }, + "putil-varhelpers": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/putil-varhelpers/-/putil-varhelpers-1.2.2.tgz", + "integrity": "sha512-AsTu08dlLFN6dmNY2YZEjJdUi9KBvpKi4PQU5Jg1sgWdCUowh94dGem5dClgzPj3kpqEd7nJvfkR6AQdHN3nhA==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -2615,11 +4623,60 @@ "safe-buffer": "^5.1.0" } }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "dependencies": { + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + } + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, "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==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2633,14 +4690,12 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "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==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -2653,6 +4708,23 @@ "picomatch": "^2.2.1" } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "^1.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", @@ -2668,11 +4740,66 @@ "es6-error": "^4.0.1" } }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + } + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==" + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, "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 + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", @@ -2684,17 +4811,43 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, "requires": { "path-parse": "^1.0.6" } }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, "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 }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -2719,8 +4872,15 @@ "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==", - "dev": true + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } }, "semver": { "version": "7.3.2", @@ -2728,6 +4888,14 @@ "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "requires": { + "sver-compat": "^1.5.0" + } + }, "serialize-javascript": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", @@ -2740,8 +4908,28 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } }, "shebang-command": { "version": "2.0.0", @@ -2781,11 +4969,137 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } }, "source-map-support": { "version": "0.5.19", @@ -2805,6 +5119,16 @@ } } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" + }, "spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -2830,12 +5154,87 @@ } } }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "stackframe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", + "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==" + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -2886,7 +5285,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" }, @@ -2894,8 +5292,7 @@ "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==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -2929,6 +5326,15 @@ "has-flag": "^3.0.0" } }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -2964,12 +5370,78 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2979,6 +5451,14 @@ "is-number": "^7.0.0" } }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "requires": { + "through2": "^2.0.3" + } + }, "ts-cleanup": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/ts-cleanup/-/ts-cleanup-0.2.2.tgz", @@ -3111,6 +5591,11 @@ "tslib": "^1.8.1" } }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3126,6 +5611,11 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -3141,6 +5631,106 @@ "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==", "dev": true }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + }, + "undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "dependencies": { + "fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=" + } + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=" + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", @@ -3150,11 +5740,20 @@ "punycode": "^2.1.0" } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { "version": "3.4.0", @@ -3168,6 +5767,89 @@ "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", "dev": true }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=" + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3262,8 +5944,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", @@ -3286,6 +5967,11 @@ "typedarray-to-buffer": "^3.1.5" } }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/package.json b/package.json index 3021b27..dac2138 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "postgresql-client", "description": "Advanced PostgreSQL client for JavaScript and TypeScript", - "version": "0.0.1", + "version": "1.0.0-beta.1", "author": "Panates", "contributors": [ "Eray Hanoglu " @@ -24,8 +24,11 @@ "rdbms" ], "dependencies": { + "doublylinked": "^2.4.0", + "lightning-pool": "^2.3.0", + "postgres-bytea": "^3.0.0", "putil-taskqueue": "^2.5.1", - "postgres-bytea": "^3.0.0" + "putil-varhelpers": "^1.2.2" }, "devDependencies": { "@types/mocha": "^8.0.3", @@ -33,6 +36,7 @@ "@typescript-eslint/eslint-plugin": "^4.4.1", "@typescript-eslint/parser": "^4.2.0", "babel-eslint": "^10.1.0", + "dotenv": "^8.2.0", "eslint": "^7.9.0", "eslint-config-google": "^0.14.0", "mocha": "^8.1.3", diff --git a/src/Connection.ts b/src/Connection.ts index 6e92212..341bd85 100644 --- a/src/Connection.ts +++ b/src/Connection.ts @@ -3,39 +3,43 @@ import {PgSocket} from './protocol/PgSocket'; import {SafeEventEmitter} from './SafeEventEmitter'; import { ConnectionConfiguration, - ConnectionState, Maybe, OID, + ConnectionState, Maybe, OID, StatementPrepareOptions, QueryOptions, QueryResult, ScriptExecuteOptions, - ScriptResult + ScriptResult, DataTypeOIDs } from './definitions'; import {PreparedStatement} from './PreparedStatement'; import {ScriptExecutor} from './ScriptExecutor'; import {BindParam} from './BindParam'; -import {DataTypeRegistry} from './DataTypeRegistry'; -import {parseConnectionString} from './helpers/parse-connectionstring'; +import {GlobalTypeMap} from './DataTypeMap'; +import {getConnectionConfig} from './helpers/connection-config'; +import {escapeLiteral} from './helpers/escape-literal'; export class Connection extends SafeEventEmitter { - private _socket: PgSocket; - private _statementQueue = new TaskQueue(); - private _activeQuery?: ScriptExecutor | PreparedStatement; + protected _socket: PgSocket; + protected _statementQueue = new TaskQueue(); + protected _activeQuery?: ScriptExecutor | PreparedStatement; + protected _config: ConnectionConfiguration; - constructor(config: ConnectionConfiguration | string) { + constructor(config?: ConnectionConfiguration | string) { super(); - if (typeof config === 'string') - config = parseConnectionString(config); - this._socket = new PgSocket(config); + this._config = getConnectionConfig(config); + this._socket = new PgSocket(this._config); this._socket.on('error', (err) => this._onError(err)); this._socket.on('close', () => this.emit('close')); this._socket.on('connecting', () => this.emit('connecting')); } + /** + * Returns current state of the connection + */ get state(): ConnectionState { return this._socket.state; } - connect(): Promise { - return new Promise((resolve, reject) => { + async connect(): Promise { + await new Promise((resolve, reject) => { if (this._socket.state === ConnectionState.READY) return resolve(); const handleConnectError = (err) => reject(err); @@ -47,48 +51,71 @@ export class Connection extends SafeEventEmitter { this._socket.once('error', handleConnectError); this._socket.connect(); }); + if (this._config.searchPath) + await this.execute('SET search_path = ' + escapeLiteral(this._config.searchPath)); + if (this._config.timezone) + await this.execute('SET timezone TO ' + escapeLiteral(this._config.timezone)); } async close(terminateWait?: number): Promise { if (this.state === ConnectionState.CLOSED) return; this._statementQueue.clear(); - const tw = terminateWait == null ? 1000 : terminateWait; - if (this._activeQuery && tw > 0) { - const startTime = Date.now(); - const timer = setInterval(() => { - if (!this._activeQuery || Date.now() > startTime + tw) { + + return new Promise(resolve => { + const close = () => { + this._socket.once('close', resolve); + this._closeSocket(); + } + if (this._activeQuery) { + const terminate = () => { + const activeQuery = this._activeQuery; this._activeQuery = undefined; - this.emit('terminate'); - clearInterval(timer); - this._terminate(); + this.emit('terminate', activeQuery); + close(); } - }, 50); - } else { - this._terminate(); - } - return new Promise(resolve => { - this._socket.once('close', resolve); - }) + const ms = terminateWait == null ? 10000 : terminateWait; + if (ms > 0) { + const startTime = Date.now(); + const timer = setInterval(() => { + if (!this._activeQuery || Date.now() > startTime + ms) { + clearInterval(timer); + terminate(); + } + }, 50); + return; + } + terminate(); + } else + close(); + }); } - async execute(sql, options?: ScriptExecuteOptions): Promise { + async execute(sql: string, options?: ScriptExecuteOptions): Promise { const script = new ScriptExecutor(this); return script.execute(sql, options); } async query(sql: string, options?: QueryOptions): Promise { - const paramTypes: Maybe[]> = options?.params?.map(prm => - prm instanceof BindParam ? prm.oid : - (DataTypeRegistry.determine(prm)) + const typeMap = options?.typeMap || GlobalTypeMap; + const paramTypes: Maybe = options?.params?.map(prm => + prm instanceof BindParam ? prm.oid : typeMap.determine(prm) || DataTypeOIDs.Varchar ); - const params: Maybe[]> = options?.params?.map(prm => - prm instanceof BindParam ? prm.value : prm); - const statement = new PreparedStatement(this, sql, undefined, paramTypes); - return statement.execute({...options, params}); + const statement = await this.prepare(sql, {paramTypes, typeMap}); + try { + const params: Maybe[]> = options?.params?.map(prm => + prm instanceof BindParam ? prm.value : prm); + return await statement.execute({...options, params}); + } finally { + await statement.close(); + } } - private _terminate(): void { + async prepare(sql: string, options?: StatementPrepareOptions): Promise { + return await PreparedStatement.prepare(this, sql, options); + } + + protected _closeSocket(): void { if (this._socket.state === ConnectionState.CLOSED) return; this._socket.sendTerminateMessage(); @@ -102,4 +129,3 @@ export class Connection extends SafeEventEmitter { } } - diff --git a/src/Cursor.ts b/src/Cursor.ts index 4712346..1bc5027 100644 --- a/src/Cursor.ts +++ b/src/Cursor.ts @@ -1,32 +1,77 @@ +import TaskQueue from 'putil-taskqueue'; +import DoublyLinked from 'doublylinked'; import {SafeEventEmitter} from './SafeEventEmitter'; -import {Protocol} from './protocol/protocol'; -import RowDescription = Protocol.RowDescription; import {Portal} from './Portal'; -import {AnyParseFunction} from './definitions'; +import {AnyParseFunction, FieldInfo, QueryOptions} from './definitions'; + +import {PreparedStatement} from './PreparedStatement'; +import {convertRowToObject, parseRow} from './common'; export class Cursor extends SafeEventEmitter { - private readonly _fetchCount: number; - private readonly _objectRows: boolean; + private readonly _statement: PreparedStatement; + private readonly _portal: Portal; private readonly _parsers: AnyParseFunction[]; + private readonly _queryOptions: QueryOptions; + private _taskQueue = new TaskQueue(); + private _rows = new DoublyLinked(); + private _closed = false; + readonly fields: FieldInfo[]; - constructor(private readonly _portal: Portal, - public readonly fields: RowDescription[], + constructor(statement: PreparedStatement, + portal: Portal, + fields: FieldInfo[], parsers: AnyParseFunction[], - fetchCount?: number, - objectRows?: boolean) { + queryOptions: QueryOptions) { super(); + this._statement = statement; + this._portal = portal; this._parsers = parsers; - this._fetchCount = fetchCount || 100; - this._objectRows = !!objectRows; + this._queryOptions = queryOptions; + this.fields = fields; } async next(): Promise { - + if (!this._rows.length) { + if (this._closed) + return; + await this._fetchRows(); + } + return this._rows.shift(); } - private async _fetchMore(): Promise { + async close(): Promise { + if (this._closed) + return; + await this._portal.close(); + await this._statement.close(); + this.emit('close'); + this._closed = true; + } + private async _fetchRows(): Promise { + const portal = this._portal; + await this._taskQueue.enqueue(async () => { + const queryOptions = this._queryOptions; + const r = await portal.execute(queryOptions.fetchCount || 100); + if (r && r.rows && r.rows.length) { + if (this._parsers) { + const objectRows = queryOptions.objectRows; + const fields = this.fields; + const rows = r.rows; + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + parseRow(this._parsers, row, this._queryOptions); + if (objectRows) + rows[i] = convertRowToObject(fields, row); + } + } + this._rows.push(...r.rows); + this.emit('fetch', r.rows); + } else { + await this.close(); + } + }); } } diff --git a/src/DataTypeMap.ts b/src/DataTypeMap.ts new file mode 100644 index 0000000..79af1fa --- /dev/null +++ b/src/DataTypeMap.ts @@ -0,0 +1,98 @@ +import { + DataType, DataTypeOIDs, + Maybe, + OID +} from './definitions'; + +import {ArrayBoolType, BoolType} from './data-types/BoolType'; +import {ArrayInt2Type, Int2Type} from './data-types/Int2Type'; +import {ArrayInt4Type, Int4Type} from './data-types/Int4Type'; +import {ArrayInt8Type, Int8Type} from './data-types/Int8Type'; +import {ArrayFloat4Type, Float4Type} from './data-types/Float4Type'; +import {ArrayFloat8Type, Float8Type} from './data-types/Float8Type'; +import {ArrayOidType, OidType} from './data-types/OidType'; +import {ArrayDateType, DateType} from './data-types/DateType'; +import {ArrayTimestampType, TimestampType} from './data-types/TimestampType'; +import {ArrayTimestamptzType, TimestamptzType} from './data-types/TimestamptzType'; +import {ArrayCharType, CharType} from './data-types/CharType'; +import {ArrayVarcharType, VarcharType} from './data-types/VarcharType'; +import {ArrayJsonType, JsonType} from './data-types/JsonType'; +import {ArrayByteaType, ByteaType} from './data-types/ByteaType'; +import {ArrayLsegType, LsegType} from './data-types/LsegType'; +import {ArrayPointType, PointType} from './data-types/PointType'; +import {ArrayCircleType, CircleType} from './data-types/CircleType'; +import {ArrayBoxType, BoxType} from './data-types/BoxType'; + +export class DataTypeMap { + private _items: Record = {}; + + constructor(other?: DataTypeMap) { + if (other instanceof DataTypeMap) + Object.assign(this._items, other._items); + } + + get(oid: OID): DataType { + return this._items[oid]; + } + + register(...dataTypes: DataType[]): void { + dataTypes.every(t => this._items[t.oid] = t); + } + + determine(value: any): Maybe { + const valueIsArray = Array.isArray(value); + for (const t of Object.values(this._items)) { + if (valueIsArray) { + if (t.elementsOID && t.isType(value[0])) + return t.oid; + } else if (!t.elementsOID && t.isType(value)) + return t.oid; + } + } + +} + +export const GlobalTypeMap = new DataTypeMap(); + + +GlobalTypeMap.register(BoolType, ArrayBoolType); +GlobalTypeMap.register(Int4Type, ArrayInt4Type, Int8Type, ArrayInt8Type, Int2Type, ArrayInt2Type); +GlobalTypeMap.register(Float8Type, ArrayFloat8Type, Float4Type, ArrayFloat4Type); + +GlobalTypeMap.register(VarcharType, ArrayVarcharType); +GlobalTypeMap.register(CharType, ArrayCharType); + +GlobalTypeMap.register(TimestamptzType, ArrayTimestamptzType); +GlobalTypeMap.register(TimestampType, ArrayTimestampType); +GlobalTypeMap.register(DateType, ArrayDateType); + +GlobalTypeMap.register(OidType, ArrayOidType); +GlobalTypeMap.register(JsonType, ArrayJsonType); +GlobalTypeMap.register(ByteaType, ArrayByteaType); + +GlobalTypeMap.register(PointType, ArrayPointType); +GlobalTypeMap.register(CircleType, ArrayCircleType); +GlobalTypeMap.register(LsegType, ArrayLsegType); +GlobalTypeMap.register(BoxType, ArrayBoxType); + +GlobalTypeMap.register({...VarcharType, name: 'bpchar', oid: DataTypeOIDs.Bpchar}); +GlobalTypeMap.register({ + ...ArrayVarcharType, + name: '_bpchar', + oid: DataTypeOIDs.ArrayBpchar, + elementsOID: DataTypeOIDs.Bpchar +}); +GlobalTypeMap.register({...VarcharType, name: 'text', oid: DataTypeOIDs.Text}); +GlobalTypeMap.register({ + ...ArrayVarcharType, + name: '_text', + oid: DataTypeOIDs.ArrayText, + elementsOID: DataTypeOIDs.Text +}); +GlobalTypeMap.register({...VarcharType, name: 'xml', oid: DataTypeOIDs.Xml}); +GlobalTypeMap.register({ + ...ArrayVarcharType, + name: '_xml', + oid: DataTypeOIDs.ArrayXml, + elementsOID: DataTypeOIDs.Xml +}); diff --git a/src/DataTypeRegistry.ts b/src/DataTypeRegistry.ts deleted file mode 100644 index ea1b760..0000000 --- a/src/DataTypeRegistry.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { - DataType, - DataTypeOIDs, - Maybe, - OID -} from './definitions'; - -import {BoolType} from './data-types/BoolType'; -import {Int2Type} from './data-types/Int2Type'; -import {Int4Type} from './data-types/Int4Type'; -import {Int8Type} from './data-types/Int8Type'; -import {Float4Type} from './data-types/Float4Type'; -import {Float8Type} from './data-types/Float8Type'; -import {OidType} from './data-types/OidType'; -import {DateType} from './data-types/DateType'; -import {TimestampType} from './data-types/TimestampType'; -import {TimestamptzType} from './data-types/TimestamptzType'; -import {CharType} from './data-types/CharType'; -import {VarcharType} from './data-types/VarcharType'; -import {JsonType} from './data-types/JsonType'; -import {ByteaType} from './data-types/ByteaType'; -import {LsegType} from './data-types/LsegType'; -import {PointType} from './data-types/PointType'; -import {CircleType} from './data-types/CircleType'; -import {BoxType} from './data-types/BoxType'; - -const items: Record = {}; - -export const DataTypeRegistry = { - get items(): Record { - return items; - }, - - register(name: string, - oid: number, - arrayOid: Maybe, type: DataType): void { - items[oid] = { - name, - oid, - arrayOid, - type - }; - if (arrayOid) - items[arrayOid] = { - name: '_' + name, - oid: arrayOid, - elementsOid: oid, - isArray: true, - type - }; - }, - - determine(value: any): Maybe { - const valueIsArray = Array.isArray(value); - for (const t of Object.values(items)) { - if (valueIsArray) { - if (t.isArray && t.type.isType(value[0])) - return t.oid; - } else if (!t.isArray && t.type.isType(value)) - return t.oid; - } - } - -} - -interface DatatypeRegistryItem { - name: string; - oid: number; - arrayOid?: number, - elementsOid?: number; - type: DataType; - isArray?: boolean; -} - -// Warning: Do not change order below! -DataTypeRegistry.register('bool', DataTypeOIDs.Bool, DataTypeOIDs.ArrayBool, BoolType); -DataTypeRegistry.register('int4', DataTypeOIDs.Int4, DataTypeOIDs.ArrayInt4, Int4Type); -DataTypeRegistry.register('int8', DataTypeOIDs.Int8, DataTypeOIDs.ArrayInt8, Int8Type); -DataTypeRegistry.register('float8', DataTypeOIDs.Float8, DataTypeOIDs.ArrayFloat8, Float8Type); -DataTypeRegistry.register('varchar', DataTypeOIDs.Varchar, DataTypeOIDs.ArrayVarchar, VarcharType); -DataTypeRegistry.register('char', DataTypeOIDs.Char, DataTypeOIDs.ArrayChar, CharType); -DataTypeRegistry.register('json', DataTypeOIDs.Json, DataTypeOIDs.ArrayJson, JsonType); -DataTypeRegistry.register('timestamptz', DataTypeOIDs.Timestamptz, DataTypeOIDs.ArrayTimestamptz, TimestamptzType); -DataTypeRegistry.register('bytea', DataTypeOIDs.Bytea, DataTypeOIDs.ArrayBytea, ByteaType); -DataTypeRegistry.register('point', DataTypeOIDs.Point, DataTypeOIDs.ArrayPoint, PointType); -DataTypeRegistry.register('circle', DataTypeOIDs.Circle, DataTypeOIDs.ArrayCircle, CircleType); -DataTypeRegistry.register('lseg', DataTypeOIDs.Lseg, DataTypeOIDs.ArrayLseg, LsegType); -DataTypeRegistry.register('box', DataTypeOIDs.Box, DataTypeOIDs.ArrayBox, BoxType); - -DataTypeRegistry.register('int2', DataTypeOIDs.Int2, DataTypeOIDs.ArrayInt2, Int2Type); -DataTypeRegistry.register('float4', DataTypeOIDs.Float4, DataTypeOIDs.ArrayFloat4, Float4Type); -DataTypeRegistry.register('oid', DataTypeOIDs.Oid, DataTypeOIDs.ArrayOid, OidType); -DataTypeRegistry.register('bpchar', DataTypeOIDs.Bpchar, DataTypeOIDs.ArrayBpchar, VarcharType); -DataTypeRegistry.register('text', DataTypeOIDs.Text, DataTypeOIDs.ArrayText, VarcharType); -DataTypeRegistry.register('xml', DataTypeOIDs.Xml, DataTypeOIDs.ArrayXml, VarcharType); -DataTypeRegistry.register('timestamp', DataTypeOIDs.Timestamp, DataTypeOIDs.ArrayTimestamp, TimestampType); -DataTypeRegistry.register('date', DataTypeOIDs.Date, DataTypeOIDs.ArrayDate, DateType); - diff --git a/src/Pool.ts b/src/Pool.ts new file mode 100644 index 0000000..9602c7e --- /dev/null +++ b/src/Pool.ts @@ -0,0 +1,153 @@ +import {createPool, IPoolFactory, Pool as LightningPool, PoolOptions, PoolState} from 'lightning-pool'; +import {coerceToBoolean, coerceToInt} from 'putil-varhelpers'; +import { + PoolConfiguration, + ConnectionState, + QueryOptions, + QueryResult, + ScriptExecuteOptions, + ScriptResult, StatementPrepareOptions +} from './definitions'; +import {PoolConnection} from './PoolConnection'; +import {getConnectionConfig} from './helpers/connection-config'; +import {PreparedStatement} from './PreparedStatement'; +import {SafeEventEmitter} from './SafeEventEmitter'; + +export class Pool extends SafeEventEmitter { + + private readonly _pool: LightningPool; + readonly config: PoolConfiguration; + + constructor(config?: PoolConfiguration | string) { + super(); + const cfg = getConnectionConfig(config) as PoolConfiguration; + this.config = cfg; + const poolOptions: PoolOptions = {}; + poolOptions.acquireMaxRetries = coerceToInt(cfg.acquireMaxRetries, 0); + poolOptions.acquireRetryWait = coerceToInt(cfg.acquireRetryWait, 2000); + poolOptions.acquireTimeoutMillis = coerceToInt(cfg.acquireTimeoutMillis, 0); + poolOptions.idleTimeoutMillis = coerceToInt(cfg.idleTimeoutMillis, 30000); + poolOptions.max = coerceToInt(cfg.max, 10); + poolOptions.maxQueue = coerceToInt(cfg.maxQueue, 1000); + poolOptions.max = coerceToInt(cfg.max, 10); + poolOptions.min = coerceToInt(cfg.min, 0); + poolOptions.minIdle = coerceToInt(cfg.minIdle, 0); + poolOptions.validation = coerceToBoolean(cfg.validation, false); + const poolFactory: IPoolFactory = { + create: async () => { + const connection = new PoolConnection(this, cfg); + connection.on('close', () => this.release(connection)); + await connection.connect(); + return connection; + }, + destroy: connection => connection.close(), + reset: async (connection: PoolConnection) => { + if (connection.state === ConnectionState.READY) + await connection.execute('ROLLBACK;') + }, + validate: async (connection: PoolConnection) => { + if (connection.state !== ConnectionState.READY) + throw new Error('Connection is not active'); + await connection.execute('select 1;'); + }, + }; + + this._pool = createPool(poolFactory, poolOptions); + this._pool.on('return', (...args) => this.emit('release', ...args)); + this._pool.on('error', (...args) => this.emit('error', ...args)); + this._pool.on('acquire', (...args) => this.emit('acquire', ...args)); + this._pool.on('destroy', (...args) => this.emit('destroy', ...args)); + this._pool.start(); + } + + /** + * Returns number of connections that are currently acquired + */ + get acquiredConnections() { + return this._pool.acquired; + } + + /** + * Returns number of unused connections in the pool + */ + get idleConnections() { + return this._pool.available; + } + + /** + * Returns total number of connections in the pool + * regardless of whether they are idle or in use + */ + get totalConnections() { + return this._pool.size; + } + + /** + * Obtains a connection from the connection pool. + */ + async acquire(): Promise { + return await this._pool.acquire(); + } + + /** + * Shuts down the pool and destroys all resources. + */ + async close(terminateWait?: number): Promise { + if (this._pool.state === PoolState.CLOSED) + return; + this._pool.close(false, () => 0); + return new Promise(resolve => { + const ms = terminateWait == null ? 10000 : terminateWait; + if (ms > 0) { + const startTime = Date.now(); + const timer = setInterval(() => { + if (this._pool.acquired === 0 || Date.now() > startTime + ms) { + clearInterval(timer); + this._pool.close(true, resolve); + } + }, 50); + return; + } + this._pool.close(true, resolve); + }); + } + + /** + * Executes a script + */ + async execute(sql: string, options?: ScriptExecuteOptions): Promise { + const connection = await this.acquire(); + try { + return await connection.execute(sql, options); + } finally { + await this.release(connection); + } + } + + /** + * Executes a query + */ + async query(sql: string, options?: QueryOptions): Promise { + const connection = await this.acquire(); + try { + return await connection.query(sql, options); + } finally { + await this.release(connection); + } + } + + async prepare(sql: string, options?: StatementPrepareOptions): Promise { + const connection = await this.acquire(); + const statement = await connection.prepare(sql, options); + statement.once('close', () => this.release(connection).catch(() => 0)); + return statement; + } + + /** + * Releases a connection + */ + async release(connection: PoolConnection): Promise { + return this._pool.release(connection); + } + +} diff --git a/src/PoolConnection.ts b/src/PoolConnection.ts new file mode 100644 index 0000000..16b03c8 --- /dev/null +++ b/src/PoolConnection.ts @@ -0,0 +1,19 @@ +import {Connection} from './Connection'; +import {ConnectionConfiguration} from './definitions'; +import {Pool} from './Pool'; + +export class PoolConnection extends Connection { + + constructor(private _pool: Pool, config: ConnectionConfiguration | string) { + super(config); + } + + async release(terminateWait?: number): Promise { + this._statementQueue.clear(); + if (this._activeQuery) { + await this.close(terminateWait); + } else + await this._pool.release(this); + } + +} diff --git a/src/Portal.ts b/src/Portal.ts index 2cfc7fd..8ae8bde 100644 --- a/src/Portal.ts +++ b/src/Portal.ts @@ -1,9 +1,10 @@ import {Connection} from './Connection'; -import {FetchOptions, Maybe} from './definitions'; +import {Maybe, QueryOptions} from './definitions'; import {Protocol} from './protocol/protocol'; import {getSocket} from './common'; import {PgSocket} from './protocol/PgSocket'; import {PreparedStatement} from './PreparedStatement'; +import {GlobalTypeMap} from './DataTypeMap'; export interface PortalExecuteResult { code: Protocol.BackendMessageCode; @@ -34,16 +35,17 @@ export class Portal { } async bind(params: Maybe, - fetchOptions: FetchOptions): Promise { + queryOptions: QueryOptions): Promise { const socket = this._socket; - this._columnFormat = fetchOptions.columnFormat != null ? - fetchOptions.columnFormat : Protocol.DataFormat.binary; + this._columnFormat = queryOptions.columnFormat != null ? + queryOptions.columnFormat : Protocol.DataFormat.binary; socket.sendBindMessage({ + typeMap: queryOptions.typeMap || GlobalTypeMap, statement: this._statement.name, portal: this.name, paramTypes: this._statement.paramTypes, params, - fetchOptions: fetchOptions + queryOptions: queryOptions }); socket.sendFlushMessage(); return socket.capture(async (code: Protocol.BackendMessageCode, msg: any, diff --git a/src/PreparedStatement.ts b/src/PreparedStatement.ts index fd53976..5de23dc 100644 --- a/src/PreparedStatement.ts +++ b/src/PreparedStatement.ts @@ -1,12 +1,9 @@ -import crypto from "crypto"; import { AnyParseFunction, CommandResult, - Maybe, OID, + Maybe, OID, StatementPrepareOptions, QueryOptions, - QueryResult, - ScriptResult, - StatementState + QueryResult } from './definitions'; import {Connection} from './Connection'; import {SafeEventEmitter} from './SafeEventEmitter'; @@ -22,28 +19,57 @@ import { parseRow, wrapRowDescription } from './common'; +import {GlobalTypeMap} from './DataTypeMap'; + +let statementCounter = 0; +let portalCounter = 0; export class PreparedStatement extends SafeEventEmitter { private readonly _connection: Connection; private readonly _socket: PgSocket; - private readonly _sql: string; - private readonly _name?: string; + private readonly _sql: string = ''; + private readonly _name: string = ''; private readonly _paramTypes: Maybe[]>; - private _prepared = false; - private _state = StatementState.IDLE; + private _refcount = 0; - constructor(connection: Connection, - sql: string, - name?: string, - paramTypes?: Maybe[]) { + constructor(connection: Connection, sql: string, paramTypes?: OID[]) { super(); this._connection = connection; this._socket = getSocket(this.connection); + this._name = 'S_' + (statementCounter++); this._sql = sql; - this._name = name; this._paramTypes = paramTypes; } + static async prepare(connection: Connection, + sql: string, + options?: StatementPrepareOptions): Promise { + const queue = getStatementQueue(connection); + const statement = new PreparedStatement(connection, sql, options?.paramTypes); + const socket = statement._socket; + await queue.enqueue(() => { + socket.sendParseMessage({ + statement: statement.name, + sql: statement.sql, + paramTypes: statement.paramTypes + }); + socket.sendFlushMessage(); + return socket.capture(async (code: Protocol.BackendMessageCode, msg: any, done: (err?: Error, result?: CommandResult) => void) => { + switch (code) { + case Protocol.BackendMessageCode.NoticeResponse: + break; + case Protocol.BackendMessageCode.ParseComplete: + done(); + break; + default: + done(new Error(`Server returned unexpected response message (0x${code.toString(16)})`)); + } + }); + }); + statement._refcount = 1; + return statement; + } + get connection(): Connection { return this._connection; } @@ -52,10 +78,6 @@ export class PreparedStatement extends SafeEventEmitter { return this._name; } - get state(): StatementState { - return this._state; - } - get sql(): string { return this._sql; } @@ -66,37 +88,32 @@ export class PreparedStatement extends SafeEventEmitter { async execute(options: QueryOptions = {}): Promise { const queue = getStatementQueue(this.connection); - return queue.enqueue(async (): Promise => { - this._state = StatementState.EXECUTING; - const prepared = this._prepared; + return queue.enqueue(async (): Promise => { let portal: Maybe; try { const result: QueryResult = {command: undefined}; const startTime = Date.now(); let t = Date.now(); - await this._prepare(); - result.prepareTime = Date.now() - t; - t = Date.now(); // Create portal - const portalName = options.cursor ? - 'P_' + crypto.randomBytes(8).toString('hex') : ''; + const portalName = 'P_' + (++portalCounter); portal = new Portal(this, portalName); await portal.bind(options.params, options); const fields = await portal.retrieveFields(); if (fields) { - const parsers: AnyParseFunction[] = getParsers(fields); - const resultFields = wrapRowDescription(fields); + const typeMap = options.typeMap || GlobalTypeMap; + const parsers: AnyParseFunction[] = getParsers(typeMap, fields); + const resultFields = wrapRowDescription(typeMap, fields); if (options.cursor) { - const cursor = new Cursor( + result.cursor = new Cursor( + this, portal, resultFields, parsers, - options.fetchCount, - options.objectRows); - result.cursor = cursor; + options); + this._refcount++; portal = undefined; return result; } @@ -115,7 +132,7 @@ export class PreparedStatement extends SafeEventEmitter { row = rows[i]; parseRow(parsers, row, options); if (options.objectRows) { - rows[i] = convertRowToObject(fields, row); + rows[i] = convertRowToObject(resultFields, row); } } } @@ -124,76 +141,38 @@ export class PreparedStatement extends SafeEventEmitter { result.command === 'UPDATE') result.rowsAffected = executeResult.rowCount; } - result.totalTime = Date.now() - startTime; + result.executeTime = Date.now() - startTime; return result; } finally { if (portal) await portal.close(); - if (!prepared) - await this._close(); - this._state = StatementState.IDLE; } }); } - async prepare(): Promise { - if (this._prepared) return; - const queue = getStatementQueue(this.connection); - return queue.enqueue(() => this._prepare()); - } - async close(): Promise { - if (this._prepared) return; + if (--this._refcount > 0) return; const queue = getStatementQueue(this.connection); - return queue.enqueue(() => this._close()); - } - - private async _prepare(): Promise { - if (this._prepared) return; - this._state = StatementState.PREPARING; - const socket = getSocket(this.connection); - socket.sendParseMessage({ - statement: this.name, - sql: this.sql, - paramTypes: this.paramTypes - }); - socket.sendFlushMessage(); - return socket.capture(async (code: Protocol.BackendMessageCode, msg: any, done: (err?: Error, result?: CommandResult) => void) => { - switch (code) { - case Protocol.BackendMessageCode.NoticeResponse: - this.emit('notice', msg); - break; - case Protocol.BackendMessageCode.ParseComplete: - this._prepared = true; - this._state = StatementState.IDLE; - done(); - break; - default: - this._state = StatementState.IDLE; - done(new Error(`Server returned unexpected response message (0x${code.toString(16)})`)); - } - }); - } - - private async _close(): Promise { - const socket = this._socket; - await socket.sendCloseMessage({type: 'P', name: this.name}); - await socket.sendSyncMessage(); - return socket.capture(async (code: Protocol.BackendMessageCode, msg: any, done: (err?: Error) => void) => { - switch (code) { - case Protocol.BackendMessageCode.NoticeResponse: - this.emit('notice', msg); - break; - case Protocol.BackendMessageCode.CloseComplete: - this._prepared = false; - break; - case Protocol.BackendMessageCode.ReadyForQuery: - done(); - break; - default: - done(new Error(`Server returned unexpected response message (0x${code.toString(16)})`)); - } + await queue.enqueue(async () => { + const socket = this._socket; + await socket.sendCloseMessage({type: 'S', name: this.name}); + await socket.sendSyncMessage(); + return socket.capture(async (code: Protocol.BackendMessageCode, msg: any, done: (err?: Error) => void) => { + switch (code) { + case Protocol.BackendMessageCode.NoticeResponse: + this.emit('notice', msg); + break; + case Protocol.BackendMessageCode.CloseComplete: + break; + case Protocol.BackendMessageCode.ReadyForQuery: + done(); + break; + default: + done(new Error(`Server returned unexpected response message (0x${code.toString(16)})`)); + } + }); }); + this.emit('close'); } async cancel(): Promise { diff --git a/src/ScriptExecutor.ts b/src/ScriptExecutor.ts index 684cd5e..24693dd 100644 --- a/src/ScriptExecutor.ts +++ b/src/ScriptExecutor.ts @@ -1,6 +1,5 @@ import {SafeEventEmitter} from './SafeEventEmitter'; -import {Connection} from './Connection'; -import {ScriptExecuteOptions, ScriptResult} from './definitions'; +import {CommandResult, ScriptExecuteOptions, ScriptResult} from './definitions'; import {Protocol} from './protocol/protocol'; import { convertRowToObject, @@ -10,6 +9,8 @@ import { parseRow, wrapRowDescription } from './common'; +import {Connection} from './Connection'; +import {GlobalTypeMap} from './DataTypeMap'; export class ScriptExecutor extends SafeEventEmitter { @@ -46,8 +47,9 @@ export class ScriptExecutor extends SafeEventEmitter { socket.sendQueryMessage(sql); let currentStart = Date.now(); let parsers; - let current: any = {command: undefined}; + let current: CommandResult = {command: undefined}; let fields: Protocol.RowDescription[]; + const typeMap = options.typeMap || GlobalTypeMap; return socket.capture(async (code: Protocol.BackendMessageCode, msg: any, done: (err?: Error, result?: any) => void) => { switch (code) { @@ -58,15 +60,15 @@ export class ScriptExecutor extends SafeEventEmitter { break; case Protocol.BackendMessageCode.RowDescription: fields = msg.fields; - parsers = getParsers(fields); - current.fields = wrapRowDescription(fields); + parsers = getParsers(typeMap, fields); + current.fields = wrapRowDescription(typeMap, fields); current.rows = []; break; case Protocol.BackendMessageCode.DataRow: let row = msg.columns.map((x: Buffer) => x.toString('utf8')); parseRow(parsers, row, options); - if (options.objectRows) - row = convertRowToObject(fields, row); + if (options.objectRows && current.fields) + row = convertRowToObject(current.fields, row); this.emit('row', row); current.rows = current.rows || []; current.rows.push(row); diff --git a/src/common.ts b/src/common.ts index ee40fa6..d8cc744 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,10 +1,7 @@ -import {DataTypeRegistry} from './DataTypeRegistry'; +import {DataTypeMap} from './DataTypeMap'; import {Protocol} from './protocol/protocol'; -import type { - AnyParseFunction, - FetchOptions, -} from './definitions'; -import type {Connection} from './Connection'; +import type {AnyParseFunction, DataMappingOptions, FieldInfo,} from './definitions'; +import {Connection} from './Connection'; import TaskQueue from 'putil-taskqueue'; import {PgSocket} from './protocol/PgSocket'; import {parsePostgresArray} from './helpers/parse-array'; @@ -12,30 +9,30 @@ import {decodeBinaryArray} from './helpers/decode-binaryarray'; const DefaultColumnParser = (v: any) => v; -export function getParsers(fields: Protocol.RowDescription[]): AnyParseFunction[] { +export function getParsers(typeMap: DataTypeMap, fields: Protocol.RowDescription[]): AnyParseFunction[] { const parsers = new Array(fields.length); const l = fields.length; let f: Protocol.RowDescription; let i; for (i = 0; i < l; i++) { f = fields[i]; - const dataTypeReg = DataTypeRegistry.items[f.dataTypeId]; + const dataTypeReg = typeMap.get(f.dataTypeId); if (dataTypeReg) { - const isArray = dataTypeReg.isArray; + const isArray = !!dataTypeReg.elementsOID; if (f.format === Protocol.DataFormat.binary) { - const decode = dataTypeReg.type.parseBinary; + const decode = dataTypeReg.parseBinary; if (decode) { parsers[i] = !isArray ? decode : - (v: Buffer, options: FetchOptions) => decodeBinaryArray(v, decode, options); + (v: Buffer, options: DataMappingOptions) => decodeBinaryArray(v, decode, options); } } else if (f.format === Protocol.DataFormat.text) { - const parse = dataTypeReg.type.parseText; + const parse = dataTypeReg.parseText; if (parse) { parsers[i] = !isArray ? parse : - (v: string, options: FetchOptions) => + (v: string, options: DataMappingOptions) => parsePostgresArray(v, { transform: (x => parse(x, options)), - separator: dataTypeReg.type.arraySeparator, + separator: dataTypeReg.arraySeparator, }); } } @@ -45,15 +42,16 @@ export function getParsers(fields: Protocol.RowDescription[]): AnyParseFunction[ return parsers; } -export function parseRow(parsers: AnyParseFunction[], row: any[], options: FetchOptions): void { +export function parseRow(parsers: AnyParseFunction[], row: any[], options: DataMappingOptions): void { const l = row.length; let i; for (i = 0; i < l; i++) { - row[i] = (parsers[i] as Function).call(undefined, row[i], options); + row[i] = row[i] == null ? null : + parsers[i].call(undefined, row[i], options); } } -export function convertRowToObject(fields: Protocol.RowDescription[], row: any[]): any { +export function convertRowToObject(fields: FieldInfo[], row: any[]): any { const out = {}; const l = row.length; let i; @@ -71,16 +69,20 @@ export function getSocket(connection: Connection): PgSocket { return connection['_socket'] as PgSocket; } -export function wrapRowDescription(fields: Protocol.RowDescription[]): any[] { +export function wrapRowDescription(typeMap: DataTypeMap, fields: Protocol.RowDescription[]): FieldInfo[] { return fields.map(f => { - const x: any = {...f}; - delete x.format; - if (x.fixedSize < 0) - delete x.fixedSize; - if (x.modifier < 0) - delete x.modifier; - const reg = DataTypeRegistry.items[x.dataTypeId]; - if (reg && reg.isArray) + const x: FieldInfo = { + fieldName: f.fieldName, + tableId: f.tableId, + columnId: f.columnId, + dataTypeId: f.dataTypeId + }; + if (f.fixedSize && f.fixedSize > 0) + x.fixedSize = f.fixedSize; + if (f.modifier && f.modifier > 0) + x.modifier = f.modifier; + const reg = typeMap.get(x.dataTypeId); + if (reg && reg.elementsOID) x.isArray = true; return x; }); diff --git a/src/data-types/BoolType.ts b/src/data-types/BoolType.ts index a2cfa51..ad5cb35 100644 --- a/src/data-types/BoolType.ts +++ b/src/data-types/BoolType.ts @@ -1,8 +1,11 @@ -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; export const BoolType: DataType = { + name: 'bool', + oid: DataTypeOIDs.Bool, + parseBinary(v: Buffer): boolean { return !!v.readUInt8(); }, @@ -22,3 +25,10 @@ export const BoolType: DataType = { } } + +export const ArrayBoolType: DataType = { + ...BoolType, + name: '_bool', + oid: DataTypeOIDs.ArrayBool, + elementsOID: DataTypeOIDs.Bool +} diff --git a/src/data-types/BoxType.ts b/src/data-types/BoxType.ts index 67033e5..db0c7d1 100644 --- a/src/data-types/BoxType.ts +++ b/src/data-types/BoxType.ts @@ -1,4 +1,4 @@ -import {DataType, Rectangle, Maybe} from '../definitions'; +import {DataType, DataTypeOIDs, Rectangle, Maybe} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; const BOX_PATTERN1 = /^\( *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *, *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *\)$/; @@ -7,6 +7,8 @@ const BOX_PATTERN3 = /^(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *, *(-? export const BoxType: DataType = { + name: 'box', + oid: DataTypeOIDs.Box, arraySeparator: ';', parseBinary(v: Buffer): Rectangle { @@ -47,3 +49,10 @@ export const BoxType: DataType = { } } + +export const ArrayBoxType: DataType = { + ...BoxType, + name: '_box', + oid: DataTypeOIDs.ArrayBox, + elementsOID: DataTypeOIDs.Box +} diff --git a/src/data-types/ByteaType.ts b/src/data-types/ByteaType.ts index 496b99c..6cd0251 100644 --- a/src/data-types/ByteaType.ts +++ b/src/data-types/ByteaType.ts @@ -1,9 +1,12 @@ import decodeBytea from 'postgres-bytea'; -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; export const ByteaType: DataType = { + name: 'bytea', + oid: DataTypeOIDs.Bytea, + parseBinary(v: Buffer): Buffer { return v; }, @@ -19,3 +22,11 @@ export const ByteaType: DataType = { } } + + +export const ArrayByteaType: DataType = { + ...ByteaType, + name: '_bytea', + oid: DataTypeOIDs.ArrayBytea, + elementsOID: DataTypeOIDs.Bytea +} diff --git a/src/data-types/CharType.ts b/src/data-types/CharType.ts index b827522..efc6721 100644 --- a/src/data-types/CharType.ts +++ b/src/data-types/CharType.ts @@ -1,8 +1,10 @@ -import {DataType} from '../definitions'; -import {SmartBuffer} from '../protocol/SmartBuffer'; +import {DataType, DataTypeOIDs} from '../definitions'; export const CharType: DataType = { + name: 'char', + oid: DataTypeOIDs.Char, + parseBinary(v: Buffer): string { return v.toString('utf8'); }, @@ -20,3 +22,10 @@ export const CharType: DataType = { } } + +export const ArrayCharType: DataType = { + ...CharType, + name: '_char', + oid: DataTypeOIDs.ArrayChar, + elementsOID: DataTypeOIDs.Char +} diff --git a/src/data-types/CircleType.ts b/src/data-types/CircleType.ts index d76c763..bfb2dec 100644 --- a/src/data-types/CircleType.ts +++ b/src/data-types/CircleType.ts @@ -1,4 +1,4 @@ -import {DataType, Circle, Maybe} from '../definitions'; +import {DataType, DataTypeOIDs, Circle, Maybe} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; const CIRCLE_PATTERN1 = /^< *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *, *(-?\d+\.?\d*) *>$/; @@ -8,6 +8,9 @@ const CIRCLE_PATTERN4 = /^(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *, *(-?\d+\.?\d*)$/ export const CircleType: DataType = { + name: 'circle', + oid: DataTypeOIDs.Circle, + parseBinary(v: Buffer): Circle { return { x: v.readDoubleBE(0), @@ -42,3 +45,10 @@ export const CircleType: DataType = { } } + +export const ArrayCircleType: DataType = { + ...CircleType, + name: '_circle', + oid: DataTypeOIDs.ArrayCircle, + elementsOID: DataTypeOIDs.Circle +} diff --git a/src/data-types/DateType.ts b/src/data-types/DateType.ts index 6d01a92..9eeefb7 100644 --- a/src/data-types/DateType.ts +++ b/src/data-types/DateType.ts @@ -1,12 +1,16 @@ -import {DataType, FetchOptions} from '../definitions'; +import {DataType, DataTypeOIDs, DataMappingOptions} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; +// noinspection ES6PreferShortImport import {parseDateTime} from '../helpers/parse-datetime'; const timeShift = 946684800000; export const DateType: DataType = { - parseBinary(v: Buffer, options: FetchOptions): Date | number { + name: 'date', + oid: DataTypeOIDs.Date, + + parseBinary(v: Buffer, options: DataMappingOptions): Date | number { const t = v.readInt32BE(); if (t === 0x7fffffff) return Infinity; @@ -21,7 +25,7 @@ export const DateType: DataType = { return new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()); }, - encodeBinary(buf: SmartBuffer, v: Date | number | string, options: FetchOptions): void { + encodeBinary(buf: SmartBuffer, v: Date | number | string, options: DataMappingOptions): void { if (typeof v === 'string') v = parseDateTime(v, false, false, options.utcDates); if (v === Infinity) { @@ -41,7 +45,7 @@ export const DateType: DataType = { buf.writeInt32BE(t); }, - parseText(v: string, options: FetchOptions): Date | number { + parseText(v: string, options: DataMappingOptions): Date | number { return parseDateTime(v, false, false, options.utcDates); }, @@ -50,3 +54,10 @@ export const DateType: DataType = { } } + +export const ArrayDateType: DataType = { + ...DateType, + name: '_date', + oid: DataTypeOIDs.ArrayDate, + elementsOID: DataTypeOIDs.Date +} diff --git a/src/data-types/Float4Type.ts b/src/data-types/Float4Type.ts index 30ba21b..20d38f1 100644 --- a/src/data-types/Float4Type.ts +++ b/src/data-types/Float4Type.ts @@ -1,8 +1,11 @@ -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; export const Float4Type: DataType = { + name: 'float4', + oid: DataTypeOIDs.Float4, + parseBinary(v: Buffer): number { return Math.round((v.readFloatBE(0) + Number.EPSILON) * 100) / 100; }, @@ -18,3 +21,10 @@ export const Float4Type: DataType = { } } + +export const ArrayFloat4Type: DataType = { + ...Float4Type, + name: '_float4', + oid: DataTypeOIDs.ArrayFloat4, + elementsOID: DataTypeOIDs.Float4 +} diff --git a/src/data-types/Float8Type.ts b/src/data-types/Float8Type.ts index eda8b07..1ec4b40 100644 --- a/src/data-types/Float8Type.ts +++ b/src/data-types/Float8Type.ts @@ -1,9 +1,10 @@ -import arrayParser from 'postgres-array'; -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; export const Float8Type: DataType = { + name: 'float8', + oid: DataTypeOIDs.Float8, parseBinary(v: Buffer): number { return v.readDoubleBE(0); @@ -20,3 +21,10 @@ export const Float8Type: DataType = { } } + +export const ArrayFloat8Type: DataType = { + ...Float8Type, + name: '_float8', + oid: DataTypeOIDs.ArrayFloat8, + elementsOID: DataTypeOIDs.Float8 +} diff --git a/src/data-types/Int2Type.ts b/src/data-types/Int2Type.ts index 12a1540..0cbf119 100644 --- a/src/data-types/Int2Type.ts +++ b/src/data-types/Int2Type.ts @@ -1,9 +1,13 @@ -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; +// noinspection ES6PreferShortImport import {fastParseInt} from '../helpers/fast-parseint'; export const Int2Type: DataType = { + name: 'int2', + oid: DataTypeOIDs.Int2, + parseBinary(v: Buffer): number { return v.readInt16BE(0); }, @@ -20,3 +24,10 @@ export const Int2Type: DataType = { } } + +export const ArrayInt2Type: DataType = { + ...Int2Type, + name: '_int2', + oid: DataTypeOIDs.ArrayInt2, + elementsOID: DataTypeOIDs.Int2 +} diff --git a/src/data-types/Int4Type.ts b/src/data-types/Int4Type.ts index bbc9e3f..5bf928f 100644 --- a/src/data-types/Int4Type.ts +++ b/src/data-types/Int4Type.ts @@ -1,9 +1,13 @@ -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; +// noinspection ES6PreferShortImport import {fastParseInt} from '../helpers/fast-parseint'; export const Int4Type: DataType = { + name: 'int4', + oid: DataTypeOIDs.Int4, + parseBinary(v: Buffer): number { return v.readInt32BE(0); }, @@ -20,3 +24,10 @@ export const Int4Type: DataType = { } } + +export const ArrayInt4Type: DataType = { + ...Int4Type, + name: '_int4', + oid: DataTypeOIDs.ArrayInt4, + elementsOID: DataTypeOIDs.Int4 +} diff --git a/src/data-types/Int8Type.ts b/src/data-types/Int8Type.ts index 86d1633..463d9a7 100644 --- a/src/data-types/Int8Type.ts +++ b/src/data-types/Int8Type.ts @@ -1,8 +1,11 @@ -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; export const Int8Type: DataType = { + name: 'int8', + oid: DataTypeOIDs.Int8, + parseBinary(v: Buffer): bigint { return v.readBigInt64BE(0); }, @@ -20,3 +23,10 @@ export const Int8Type: DataType = { } } + +export const ArrayInt8Type: DataType = { + ...Int8Type, + name: '_int8', + oid: DataTypeOIDs.ArrayInt8, + elementsOID: DataTypeOIDs.Int8 +} diff --git a/src/data-types/JsonType.ts b/src/data-types/JsonType.ts index 2fad3c6..5141505 100644 --- a/src/data-types/JsonType.ts +++ b/src/data-types/JsonType.ts @@ -1,7 +1,10 @@ -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; export const JsonType: DataType = { + name: 'json', + oid: DataTypeOIDs.Json, + parseBinary(v: Buffer): string { return v.toString('utf8'); }, @@ -23,3 +26,10 @@ export const JsonType: DataType = { } } + +export const ArrayJsonType: DataType = { + ...JsonType, + name: '_json', + oid: DataTypeOIDs.ArrayJson, + elementsOID: DataTypeOIDs.Json +} diff --git a/src/data-types/LsegType.ts b/src/data-types/LsegType.ts index 3fc075f..857f6d3 100644 --- a/src/data-types/LsegType.ts +++ b/src/data-types/LsegType.ts @@ -1,4 +1,4 @@ -import {DataType, Rectangle, Maybe} from '../definitions'; +import {DataType, DataTypeOIDs, Rectangle, Maybe} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; const LSEG_PATTERN1 = /^\[ *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *, *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *]$/; @@ -8,6 +8,9 @@ const LSEG_PATTERN4 = /^(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *, *(- export const LsegType: DataType = { + name: 'lseg', + oid: DataTypeOIDs.Lseg, + parseBinary(v: Buffer): Rectangle { return { x1: v.readDoubleBE(0), @@ -46,3 +49,10 @@ export const LsegType: DataType = { } } + +export const ArrayLsegType: DataType = { + ...LsegType, + name: '_lseg', + oid: DataTypeOIDs.ArrayLseg, + elementsOID: DataTypeOIDs.Lseg +} diff --git a/src/data-types/OidType.ts b/src/data-types/OidType.ts index d19eaef..5ef782e 100644 --- a/src/data-types/OidType.ts +++ b/src/data-types/OidType.ts @@ -1,9 +1,13 @@ -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; +// noinspection ES6PreferShortImport import {fastParseInt} from '../helpers/fast-parseint'; export const OidType: DataType = { + name: 'oid', + oid: DataTypeOIDs.Oid, + parseBinary(v: Buffer): number { return v.readUInt32BE(0); }, @@ -20,3 +24,10 @@ export const OidType: DataType = { } } + +export const ArrayOidType: DataType = { + ...OidType, + name: '_oid', + oid: DataTypeOIDs.ArrayOid, + elementsOID: DataTypeOIDs.Oid +} diff --git a/src/data-types/PointType.ts b/src/data-types/PointType.ts index ec5e99c..fe4d58c 100644 --- a/src/data-types/PointType.ts +++ b/src/data-types/PointType.ts @@ -1,4 +1,4 @@ -import {DataType, Maybe, Point} from '../definitions'; +import {DataType, DataTypeOIDs, Maybe, Point} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; const POINT_PATTERN1 = /^\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\)$/; @@ -6,6 +6,9 @@ const POINT_PATTERN2 = /^(-?\d+\.?\d*) *, *(-?\d+\.?\d*)$/; export const PointType: DataType = { + name: 'point', + oid: DataTypeOIDs.Point, + parseBinary(v: Buffer): Point { return { x: v.readDoubleBE(0), @@ -35,3 +38,10 @@ export const PointType: DataType = { } } + +export const ArrayPointType: DataType = { + ...PointType, + name: '_point', + oid: DataTypeOIDs.ArrayPoint, + elementsOID: DataTypeOIDs.Point +} diff --git a/src/data-types/TimestampType.ts b/src/data-types/TimestampType.ts index deacc52..33d9543 100644 --- a/src/data-types/TimestampType.ts +++ b/src/data-types/TimestampType.ts @@ -1,5 +1,6 @@ -import {DataType, FetchOptions} from '../definitions'; +import {DataType, DataTypeOIDs, DataMappingOptions} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; +// noinspection ES6PreferShortImport import {parseDateTime} from '../helpers/parse-datetime'; const timeShift = 946684800000; @@ -7,7 +8,10 @@ const timeMul = 4294967296; export const TimestampType: DataType = { - parseBinary(v: Buffer, options: FetchOptions): Date | number { + name: 'timestamp', + oid: DataTypeOIDs.Timestamp, + + parseBinary(v: Buffer, options: DataMappingOptions): Date | number { const hi = v.readInt32BE(); const lo = v.readUInt32BE(4); if (lo === 0xffffffff && hi === 0x7fffffff) return Infinity; @@ -23,7 +27,7 @@ export const TimestampType: DataType = { d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()); }, - encodeBinary(buf: SmartBuffer, v: Date | number | string, options: FetchOptions): void { + encodeBinary(buf: SmartBuffer, v: Date | number | string, options: DataMappingOptions): void { if (typeof v === 'string') v = parseDateTime(v, true, false, options.utcDates); if (v === Infinity) { @@ -48,7 +52,7 @@ export const TimestampType: DataType = { buf.writeUInt32BE(lo); }, - parseText(v: string, options: FetchOptions): Date | number { + parseText(v: string, options: DataMappingOptions): Date | number { return parseDateTime(v, true, false, options.utcDates); }, @@ -57,3 +61,10 @@ export const TimestampType: DataType = { } } + +export const ArrayTimestampType: DataType = { + ...TimestampType, + name: '_timestamp', + oid: DataTypeOIDs.ArrayTimestamp, + elementsOID: DataTypeOIDs.Timestamp +} diff --git a/src/data-types/TimestamptzType.ts b/src/data-types/TimestamptzType.ts index f025752..f9e8e93 100644 --- a/src/data-types/TimestamptzType.ts +++ b/src/data-types/TimestamptzType.ts @@ -1,5 +1,6 @@ -import {DataType, FetchOptions, Maybe} from '../definitions'; +import {DataType, DataTypeOIDs, DataMappingOptions, Maybe} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; +// noinspection ES6PreferShortImport import {parseDateTime} from '../helpers/parse-datetime'; const timeShift = 946684800000; @@ -7,7 +8,10 @@ const timeMul = 4294967296; export const TimestamptzType: DataType = { - parseBinary(v: Buffer, options: FetchOptions): Date | number { + name: 'timestamptz', + oid: DataTypeOIDs.Timestamptz, + + parseBinary(v: Buffer, options: DataMappingOptions): Date | number { const hi = v.readInt32BE(); const lo = v.readUInt32BE(4); if (lo === 0xffffffff && hi === 0x7fffffff) return Infinity; @@ -23,7 +27,7 @@ export const TimestamptzType: DataType = { d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()); }, - encodeBinary(buf: SmartBuffer, v: Date | number | string, options: FetchOptions): void { + encodeBinary(buf: SmartBuffer, v: Date | number | string, options: DataMappingOptions): void { if (typeof v === 'string') v = parseDateTime(v, true, true, options.utcDates); if (v === Infinity) { @@ -46,7 +50,7 @@ export const TimestamptzType: DataType = { buf.writeUInt32BE(lo); }, - parseText(v: string, options: FetchOptions): Maybe { + parseText(v: string, options: DataMappingOptions): Maybe { return parseDateTime(v, true, true, options.utcDates); }, @@ -55,3 +59,10 @@ export const TimestamptzType: DataType = { } } + +export const ArrayTimestamptzType: DataType = { + ...TimestamptzType, + name: '_timestamptz', + oid: DataTypeOIDs.ArrayTimestamptz, + elementsOID: DataTypeOIDs.Timestamptz +} diff --git a/src/data-types/VarcharType.ts b/src/data-types/VarcharType.ts index 3087984..ab60e08 100644 --- a/src/data-types/VarcharType.ts +++ b/src/data-types/VarcharType.ts @@ -1,8 +1,11 @@ -import {DataType} from '../definitions'; +import {DataType, DataTypeOIDs} from '../definitions'; import {SmartBuffer} from '../protocol/SmartBuffer'; export const VarcharType: DataType = { + name: 'varchar', + oid: DataTypeOIDs.Varchar, + parseBinary(v: Buffer): string { return v.toString('utf8'); }, @@ -20,3 +23,10 @@ export const VarcharType: DataType = { } } + +export const ArrayVarcharType: DataType = { + ...VarcharType, + name: '_varchar', + oid: DataTypeOIDs.ArrayVarchar, + elementsOID: DataTypeOIDs.Varchar +} diff --git a/src/definitions.ts b/src/definitions.ts index 6f66357..1d2c5eb 100644 --- a/src/definitions.ts +++ b/src/definitions.ts @@ -1,11 +1,222 @@ import tls from "tls"; -import {Cursor} from './Cursor'; -import {SmartBuffer} from './protocol/SmartBuffer'; -import {Protocol} from './protocol/protocol'; -import DataFormat = Protocol.DataFormat; +import type {Cursor} from './Cursor'; +import type {SmartBuffer} from './protocol/SmartBuffer'; +import type {Protocol} from './protocol/protocol'; +import type {PoolOptions} from 'lightning-pool'; +import {DataTypeMap} from './DataTypeMap'; +import {BindParam} from './BindParam'; export type OID = number; export type Maybe = T | undefined; +export type Nullable = T | null; +export type DataFormat = Protocol.DataFormat; + +export interface DatabaseConnectionParams { + host?: string; + port?: number; + user?: string; + password?: string | (() => string | Promise); + database?: string; + applicationName?: string; + ssl?: tls.ConnectionOptions; + timezone?: string; + searchPath?: string; + connectTimeoutMs?: number; +} + +export interface SocketOptions { + keepAlive?: boolean; +} + +export type ConnectionConfiguration = DatabaseConnectionParams & SocketOptions; + +export interface PoolConfiguration extends ConnectionConfiguration, PoolOptions { +} + +export enum ConnectionState { + CLOSED = 0, + CONNECTING = 1, + AUTHORIZING = 3, + READY = 2, + CLOSING = 10, +} + +export interface DataMappingOptions { + /** + * If true UTC time will be used for date decoding, else system time offset will be used + * @default false + */ + utcDates?: boolean; +} + +export interface ScriptExecuteOptions extends DataMappingOptions { + /** + * Specifies if rows will be fetched as pair objects or array of values + * @default false + */ + objectRows?: boolean; + /** + * Data type map instance + * @default GlobalTypeMap + */ + typeMap?: DataTypeMap; +} + +export interface StatementPrepareOptions { + /** + * Specifies data type for each parameter + */ + paramTypes?: OID[]; + /** + * Data type map instance + * @default GlobalTypeMap + */ + typeMap?: DataTypeMap; +} + +export interface QueryOptions extends DataMappingOptions { + /** + * Specifies if rows will be fetched as pair objects or array of values + * @default false + */ + objectRows?: boolean; + /** + * Data type map instance + * @default GlobalTypeMap + */ + typeMap?: DataTypeMap; + /** + * If true, returns Cursor instance instead of rows + */ + cursor?: boolean; + /** + * Query execution parameters + */ + params?: (BindParam | any)[]; + /** + * Specifies transfer format (binary or text) for each column + * @default DataFormat.binary + */ + columnFormat?: DataFormat | DataFormat[]; + /** + * Specifies how many rows will be fetched. For Cursor, this value specifies how many rows will be fetched in a batch + * @default 100 + */ + fetchCount?: number; +} + +export interface CommandResult { + /** + * Name of the command (INSERT, SELECT, UPDATE, etc.) + */ + command?: string; + /** + * Contains information about fields in column order + */ + fields?: FieldInfo[]; + /** + * Contains array of row data + */ + rows?: any[]; + /** + * Time elapsed to execute command + */ + executeTime?: number; + /** + * How many rows affected + */ + rowsAffected?: number; +} + +export interface ScriptResult { + /** + * Array of command result for each sql command in the script + */ + results: CommandResult[]; + /** + * Command count in the script + */ + totalCommands: number; + /** + * Total execution time + */ + totalTime: number; +} + +export interface FieldInfo { + /** + * Name of the field + */ + fieldName: string; + /** + * OID of the table + */ + tableId?: number; + /** + * OID of the column + */ + columnId?: number; + /** + * OID of the data type + */ + dataTypeId: number; + /** + * Data length if data type has a fixed size + */ + fixedSize?: number; + /** + * Modifier of the data type + */ + modifier?: number; + /** + * Whether the data type is an array + */ + isArray?: boolean; +} + +export interface QueryResult extends CommandResult { + /** + * Cursor instance + */ + cursor?: Cursor; +} + +export type DecodeBinaryFunction = (buf: Buffer, options: DataMappingOptions) => any; +export type EncodeBinaryFunction = (buf: SmartBuffer, v: any, options: DataMappingOptions) => void; +export type ParseTextFunction = (v: any, options: DataMappingOptions) => any; +export type EncodeTextFunction = (v: any, options: DataMappingOptions) => string; + +export type AnyParseFunction = ParseTextFunction | DecodeBinaryFunction; + +export interface DataType { + oid: OID; + name: string; + elementsOID?: OID; + arraySeparator?: string; + isType: (v: any) => boolean; + parseBinary: DecodeBinaryFunction; + parseText: ParseTextFunction; + encodeBinary?: EncodeBinaryFunction; + encodeText?: EncodeTextFunction; +} + +export interface Point { + x: number, + y: number +} + +export interface Circle { + x: number, + y: number, + r: number +} + +export interface Rectangle { + x1: number, + y1: number, + x2: number, + y2: number, +} export const DataTypeOIDs = { Bool: 16, @@ -120,109 +331,3 @@ export const DataTypeOIDs = { ArrayUuid: 2951, ArrayJsonb: 3807, } - -export interface ConnectionConfiguration { - host?: string | null; - port?: number; - user?: string | null; - password?: string | (() => string | Promise) | null; - database?: string | null; - schema?: string | null; - applicationName?: string | null; - fallbackApplicationName?: string | null; - ssl?: tls.ConnectionOptions; - /** - * Connect timeout in milliseconds - */ - connectTimeoutMs?: number; - keepAlive?: boolean; - keepAliveInitialDelayMillis?: number; -} - -export enum ConnectionState { - CLOSED = 0, - CONNECTING = 1, - AUTHORIZING = 3, - READY = 2, - CLOSING = 10, -} - -export enum StatementState { - IDLE = 0, - PREPARING = 1, - EXECUTING = 1 -} - -export interface FetchOptions { - fetchAsString?: OID[]; - fetchCount?: number; - objectRows?: boolean; - utcDates?: boolean; - columnFormat?: DataFormat | DataFormat[]; -} - -export interface ScriptExecuteOptions extends FetchOptions { -} - -export interface CommandResult { - command?: string; - fields?: any[]; - rows?: any[]; - executeTime?: number; - rowsAffected?: number; -} - -export interface ScriptResult { - results: CommandResult[]; - totalCommands: number; - totalTime: number; -} - -export interface QueryOptions extends FetchOptions { - params?: any[]; - cursor?: boolean; -} - -export type BindValue = string | Buffer | null; - -export interface QueryResult extends CommandResult { - cursor?: Cursor; - prepareTime?: number; - fetchTime?: number; - totalTime?: number; -} - -export type DecodeBinaryFunction = (buf: Buffer, options: FetchOptions) => any; -export type EncodeBinaryFunction = (buf: SmartBuffer, v: any, options: FetchOptions) => void; -export type ParseTextFunction = (v: any, options: FetchOptions) => any; -export type EncodeTextFunction = (v: any, options: FetchOptions) => string; - -export type AnyParseFunction = ParseTextFunction | DecodeBinaryFunction; - -export interface DataType { - - isType: (v: any) => boolean; - parseBinary: DecodeBinaryFunction; - parseText: ParseTextFunction; - encodeBinary?: EncodeBinaryFunction; - encodeText?: EncodeTextFunction; - arraySeparator?: string; -} - -export interface Point { - x: number, - y: number -} - -export interface Circle { - x: number, - y: number, - r: number -} - -export interface Rectangle { - x1: number, - y1: number, - x2: number, - y2: number, -} diff --git a/src/helpers/config-from-env.ts b/src/helpers/config-from-env.ts new file mode 100644 index 0000000..93d3260 --- /dev/null +++ b/src/helpers/config-from-env.ts @@ -0,0 +1,26 @@ +import {DatabaseConnectionParams} from '../definitions'; + +export function configFromEnv(): DatabaseConnectionParams { + const env = process.env; + const result: DatabaseConnectionParams = {}; + + result.host = env.PGHOST || env.PGHOSTADDR; + if (env.PGPORT) + result.port = parseInt(env.PGPORT, 10) || 5432; + if (env.PGDATABASE) + result.database = env.PGDATABASE; + if (env.PGUSER) + result.user = env.PGUSER; + if (env.PGPASSWORD) + result.password = env.PGPASSWORD; + if (env.PGAPPNAME) + result.applicationName = env.PGAPPNAME; + if (env.PGTZ) + result.timezone = env.PGTZ; + if (env.PGSEARCHPATH) + result.searchPath = env.PGSEARCHPATH; + if (env.PGCONNECT_TIMEOUT) + result.connectTimeoutMs = parseInt(env.PGCONNECT_TIMEOUT, 10); + + return result; +} diff --git a/src/helpers/parse-connectionstring.ts b/src/helpers/connection-config.ts similarity index 62% rename from src/helpers/parse-connectionstring.ts rename to src/helpers/connection-config.ts index c1674c2..1a88b93 100644 --- a/src/helpers/parse-connectionstring.ts +++ b/src/helpers/connection-config.ts @@ -1,12 +1,25 @@ import url from "url"; import {ConnectionConfiguration} from '../definitions'; +import {configFromEnv} from './config-from-env'; + +export function getConnectionConfig(config?: ConnectionConfiguration | string): ConnectionConfiguration { + if (typeof config === 'string') + return parseConnectionString(config); + const cfg = {...configFromEnv(), ...config}; + if (cfg.host) { + const x = parseConnectionString('' + cfg.host); + return {...cfg, ...x}; + } + return cfg; +} export function parseConnectionString(str: string): ConnectionConfiguration { - if (str.startsWith('unix:///') || str.startsWith('/')) { - const arr = str.split(' '); - return {host: arr[0], database: arr[1]} as ConnectionConfiguration; - } + if (str.startsWith('/')) + str = 'socket:/' + str; + + if (!str.includes('://')) + str = 'postgres://' + str; const parsed = url.parse(str, true); const getFirst = (v: string | string[] | null) => { @@ -19,7 +32,7 @@ export function parseConnectionString(str: string): ConnectionConfiguration { if (parsed.port) cfg.port = parseInt(parsed.port, 10); - if (parsed.protocol == 'socket:') { + if (parsed.protocol == 'socket:' || parsed.protocol == 'unix:') { if (!cfg.host.startsWith('/')) cfg.host = '/' + cfg.host; cfg.host += decodeURI(parsed.pathname || ''); @@ -33,15 +46,15 @@ export function parseConnectionString(str: string): ConnectionConfiguration { if (parsed.query.host) cfg.host = decodeURI(getFirst(parsed.query.host)); - if (parsed.query.schema) - cfg.schema = decodeURI(getFirst(parsed.query.schema)); + if (parsed.query.db) + cfg.database = decodeURI(getFirst(parsed.query.db)); + + if (parsed.query['search-path']) + cfg.searchPath = decodeURI(getFirst(parsed.query['search-path'])); if (parsed.query.application_name) cfg.applicationName = decodeURI(getFirst(parsed.query.application_name)); - if (parsed.query.fallback_application_name) - cfg.fallbackApplicationName = decodeURI(getFirst(parsed.query.fallback_application_name)); - if (parsed.auth) { const a = parsed.auth.split(':'); if (a[0]) diff --git a/src/helpers/decode-binaryarray.ts b/src/helpers/decode-binaryarray.ts index ea42821..1530eb8 100644 --- a/src/helpers/decode-binaryarray.ts +++ b/src/helpers/decode-binaryarray.ts @@ -1,7 +1,9 @@ -import {DecodeBinaryFunction, FetchOptions} from '../definitions'; +import {DecodeBinaryFunction, DataMappingOptions, Nullable} from '../definitions'; import {BufferReader} from '../protocol/BufferReader'; -export function decodeBinaryArray(buf: Buffer, decoder: DecodeBinaryFunction, options: FetchOptions): any[] { +export function decodeBinaryArray(buf: Buffer, decoder: DecodeBinaryFunction, options: DataMappingOptions): Nullable { + if (!buf.length) + return null; const io = new BufferReader(buf); const ndims = io.readInt32BE(); io.readInt32BE(); // hasNulls diff --git a/src/helpers/encode-binaryarray.ts b/src/helpers/encode-binaryarray.ts index 468487f..2458217 100644 --- a/src/helpers/encode-binaryarray.ts +++ b/src/helpers/encode-binaryarray.ts @@ -1,9 +1,9 @@ import {SmartBuffer} from '../protocol/SmartBuffer'; -import {DataTypeOIDs, EncodeBinaryFunction, FetchOptions, OID} from '../definitions'; +import {DataTypeOIDs, EncodeBinaryFunction, DataMappingOptions, OID} from '../definitions'; import {arrayCalculateDim} from './array-calculatedim'; export function encodeBinaryArray(io: SmartBuffer, value: any[], itemOid: OID, - options: FetchOptions, encode: EncodeBinaryFunction): Buffer { + options: DataMappingOptions, encode: EncodeBinaryFunction): Buffer { itemOid = itemOid || DataTypeOIDs.Varchar; const dim = arrayCalculateDim(value); const ndims = dim.length; diff --git a/src/helpers/stringify-arrayliteral.ts b/src/helpers/stringify-arrayliteral.ts index af7e11e..3e1db1b 100644 --- a/src/helpers/stringify-arrayliteral.ts +++ b/src/helpers/stringify-arrayliteral.ts @@ -1,7 +1,7 @@ -import {EncodeTextFunction, FetchOptions} from '../definitions'; +import {EncodeTextFunction, DataMappingOptions} from '../definitions'; import {arrayCalculateDim} from './array-calculatedim'; -export function stringifyArrayLiteral(value: any[], options?: FetchOptions, encode?: EncodeTextFunction): string { +export function stringifyArrayLiteral(value: any[], options?: DataMappingOptions, encode?: EncodeTextFunction): string { const dim = arrayCalculateDim(value); const writeDim = (arr: any[], level: number) => { const elemCount = dim[level]; diff --git a/src/helpers/stringify-for-sql.ts b/src/helpers/stringify-for-sql.ts index d9363a6..c088d5a 100644 --- a/src/helpers/stringify-for-sql.ts +++ b/src/helpers/stringify-for-sql.ts @@ -1,12 +1,12 @@ -import {EncodeTextFunction, FetchOptions} from '../definitions'; +import {EncodeTextFunction, DataMappingOptions} from '../definitions'; import {escapeLiteral} from './escape-literal'; -export function stringifyArrayForSQL(v: any[], options?: FetchOptions, encode?: EncodeTextFunction): string { +export function stringifyArrayForSQL(v: any[], options?: DataMappingOptions, encode?: EncodeTextFunction): string { const arr = v.map(x => stringifyValueForSQL(x, options, encode)); return 'ARRAY[' + arr.join(',') + ']'; } -export function stringifyValueForSQL(v: any, options?: FetchOptions, encode?: EncodeTextFunction): string { +export function stringifyValueForSQL(v: any, options?: DataMappingOptions, encode?: EncodeTextFunction): string { if (v == null) return 'null'; if (typeof v === 'boolean') diff --git a/src/index.ts b/src/index.ts index 9301bae..5785196 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,13 @@ -export {DataTypeRegistry} from './DataTypeRegistry'; +export * from './DataTypeMap'; export * from './definitions'; export * from './Connection'; +export * from './Pool'; export * from './ScriptExecutor'; +export * from './PreparedStatement'; export * from './BindParam'; export * from './helpers/stringify-arrayliteral'; export * from './helpers/stringify-for-sql'; export * from './helpers/escape-literal'; export * from './helpers/fast-parseint'; -export * from './helpers/parse-connectionstring'; +export * from './helpers/connection-config'; export * from './helpers/parse-datetime'; diff --git a/src/protocol/Backend.ts b/src/protocol/Backend.ts index 24d61d9..05a713c 100644 --- a/src/protocol/Backend.ts +++ b/src/protocol/Backend.ts @@ -60,6 +60,8 @@ export class Backend { // Set offset to next message io.offset = offsetBookmark + len + 1; } + if (io.offset < io.length) + this._buf = io.readBuffer(io.length - io.offset); } } @@ -190,8 +192,10 @@ function parseDataRow(io: BufferReader): Protocol.DataRowMessage { // Can be zero. As a special case, -1 indicates a NULL column value. // No value bytes follow in the NULL case. const l = io.readInt32BE(); - const v = io.readBuffer(l); - out.columns.push(v); + if (l < 0) + out.columns.push(null); + else + out.columns.push(io.readBuffer(l)); } } return out; diff --git a/src/protocol/BufferReader.ts b/src/protocol/BufferReader.ts index b1c2949..68d3bef 100644 --- a/src/protocol/BufferReader.ts +++ b/src/protocol/BufferReader.ts @@ -65,7 +65,7 @@ export class BufferReader { readBuffer(len?: number): Buffer { if (len) this._checkReadable(len); - const end = len ? this.offset + len : this.length; + const end = len !== undefined ? this.offset + len : this.length; const buf = this.buffer.slice(this.offset, end); this.offset = end; return buf; diff --git a/src/protocol/Frontend.ts b/src/protocol/Frontend.ts index 4d72b69..cf1efc5 100644 --- a/src/protocol/Frontend.ts +++ b/src/protocol/Frontend.ts @@ -1,10 +1,10 @@ import {Protocol} from './protocol'; import {SASL} from './sasl'; import {SmartBuffer} from './SmartBuffer'; -import {FetchOptions, Maybe, OID} from '../definitions'; -import {DataTypeRegistry} from '../DataTypeRegistry'; +import {Maybe, OID, QueryOptions} from '../definitions'; +import {DataTypeMap} from '../DataTypeMap'; import {encodeBinaryArray} from '../helpers/encode-binaryarray'; -import {stringifyArrayLiteral} from '../helpers/stringify-arrayliteral'; +import {stringifyArrayLiteral} from '..'; import DataFormat = Protocol.DataFormat; const StaticFlushBuffer = Buffer.from([Protocol.FrontendMessageCode.Flush, 0x00, 0x00, 0x00, 0x04]); @@ -21,11 +21,12 @@ export namespace Frontend { } export interface BindMessageArgs { + typeMap: DataTypeMap; statement?: string; portal?: string; paramTypes?: Maybe[]; params?: any[]; - fetchOptions: FetchOptions; + queryOptions: QueryOptions; } export interface ParseMessageArgs { @@ -136,8 +137,8 @@ export class Frontend { .writeInt32BE(0) // Preserve header .writeCString(args.portal || '', 'utf8') .writeCString(args.statement || '', 'utf8'); - const {params, paramTypes, fetchOptions} = args; - const columnFormat = fetchOptions.columnFormat != null ? fetchOptions.columnFormat: + const {params, paramTypes, queryOptions} = args; + const columnFormat = queryOptions.columnFormat != null ? queryOptions.columnFormat: DataFormat.binary; if (params && params.length) { @@ -155,26 +156,26 @@ export class Frontend { io.writeInt32BE(-1); const dataTypeOid = paramTypes ? paramTypes[i] : undefined; - const dt = dataTypeOid ? DataTypeRegistry.items[dataTypeOid] : undefined; + const dt = dataTypeOid ? args.typeMap.get(dataTypeOid) : undefined; if (dt) { - if (typeof dt.type.encodeBinary === 'function') { + if (typeof dt.encodeBinary === 'function') { // Set param format to binary io.buffer.writeInt16BE(Protocol.DataFormat.binary, formatOffset + (i * 2)); // Preserve data length io.writeInt32BE(0); const dataOffset = io.offset; - if (dt.isArray) { + if (dt.elementsOID) { // If data type is array v = Array.isArray(v) ? v : [v]; - encodeBinaryArray(io, v, dt.elementsOid as OID, fetchOptions, dt.type.encodeBinary); + encodeBinaryArray(io, v, dt.elementsOID, queryOptions, dt.encodeBinary); } else { - dt.type.encodeBinary(io, v, fetchOptions); + dt.encodeBinary(io, v, queryOptions); } io.buffer.writeInt32BE(io.length - dataOffset, dataOffset - 4); // Update length - } else if (typeof dt.type.encodeText === 'function') { - v = dt.isArray ? - stringifyArrayLiteral(v, fetchOptions, dt.type.encodeText) : - dt.type.encodeText(v, fetchOptions); + } else if (typeof dt.encodeText === 'function') { + v = dt.elementsOID ? + stringifyArrayLiteral(v, queryOptions, dt.encodeText) : + dt.encodeText(v, queryOptions); io.writeLString(v, 'utf8'); } } else if (Buffer.isBuffer(v)) { diff --git a/src/protocol/PgSocket.ts b/src/protocol/PgSocket.ts index f9d0be5..e21553e 100644 --- a/src/protocol/PgSocket.ts +++ b/src/protocol/PgSocket.ts @@ -5,7 +5,7 @@ import {SafeEventEmitter} from '../SafeEventEmitter'; import {Backend} from './Backend'; import {Frontend} from './Frontend'; import {Protocol} from './protocol'; -import {BindValue, ConnectionConfiguration, ConnectionState, DataTypeOIDs, Maybe, OID} from '../definitions'; +import {ConnectionConfiguration, ConnectionState, Maybe} from '../definitions'; import {DatabaseError} from './DatabaseError'; import {SASL} from './sasl'; @@ -56,8 +56,8 @@ export class PgSocket extends SafeEventEmitter { const connectHandler = () => { socket.setTimeout(0); - if (this.options.keepAlive) - socket.setKeepAlive(true, this.options.keepAliveInitialDelayMillis); + if (this.options.keepAlive || this.options.keepAlive == null) + socket.setKeepAlive(true); if (options.ssl) { socket.write(this._frontend.getSSLRequestMessage()); socket.once('data', (x) => { @@ -111,10 +111,6 @@ export class PgSocket extends SafeEventEmitter { socket.destroy(); } - cancelActiveQuery() { - - } - sendParseMessage(args: Frontend.ParseMessageArgs): void { this._send(this._frontend.getParseMessage(args)); } @@ -203,7 +199,7 @@ export class PgSocket extends SafeEventEmitter { socket.on('error', (err: SocketError) => this._handleError(err)); socket.on('close', () => this._handleClose()); this._send(this._frontend.getStartupMessage({ - user: this.options.user || '', + user: this.options.user || 'postgres', database: this.options.database || '' })); } @@ -223,7 +219,6 @@ export class PgSocket extends SafeEventEmitter { } protected _handleData(data: Buffer): void { - // console.log('< ', JSON.stringify(data)); this._backend.parse(data, (code: Protocol.BackendMessageCode, data?: any) => { try { switch (code) { diff --git a/src/protocol/protocol.ts b/src/protocol/protocol.ts index 7f06863..ee6b239 100644 --- a/src/protocol/protocol.ts +++ b/src/protocol/protocol.ts @@ -1,3 +1,5 @@ +import {Nullable} from '../definitions'; + export namespace Protocol { export const VERSION_MAJOR = 3; @@ -143,7 +145,7 @@ export namespace Protocol { export interface DataRowMessage { columnCount: number; - columns: Buffer[]; + columns: Nullable[]; } export interface ErrorResponseMessage { diff --git a/test/A-helpers/connection-config.spec.ts b/test/A-helpers/connection-config.spec.ts new file mode 100644 index 0000000..93c9348 --- /dev/null +++ b/test/A-helpers/connection-config.spec.ts @@ -0,0 +1,77 @@ +import assert from 'assert'; +import '../_support/env'; +import {getConnectionConfig, parseConnectionString} from '../../src'; + +describe('Parse connection string', function () { + + const oldEnv = {...process.env}; + + after(() => { + process.env = oldEnv; + }); + + describe('Parse connection string', function () { + + it('should parse local unix path ', function () { + const cfg = parseConnectionString('/var/run'); + assert.deepStrictEqual(cfg.host, '/var/run'); + }); + + it('should parse local unix path with query', function () { + const cfg = parseConnectionString('/var/run?db=mydb'); + assert.deepStrictEqual(cfg.host, '/var/run'); + assert.deepStrictEqual(cfg.database, 'mydb'); + }); + + it('should parse unix sockets uri', function () { + const cfg = parseConnectionString('socket://some path/?db=any%2bdb'); + assert.deepStrictEqual(cfg.host, '/some path/'); + assert.deepStrictEqual(cfg.database, 'any+db'); + }); + + it('should parse unix with auth', function () { + let cfg = parseConnectionString('socket://me:1234@some path/?db=any db'); + assert.deepStrictEqual(cfg.host, '/some path/'); + assert.deepStrictEqual(cfg.database, 'any db'); + assert.deepStrictEqual(cfg.password, '1234'); + assert.deepStrictEqual(cfg.user, 'me'); + }); + + it('should parse url', function () { + let cfg = parseConnectionString('postgres://me:1234@localhost/any db'); + assert.deepStrictEqual(cfg.host, 'localhost'); + assert.deepStrictEqual(cfg.database, 'any db'); + assert.deepStrictEqual(cfg.password, '1234'); + assert.deepStrictEqual(cfg.user, 'me'); + }); + + it('should get host from query', function () { + let cfg = parseConnectionString('postgres://me:1234@:5555/any db?host=127.0.0.1'); + assert.deepStrictEqual(cfg.host, '127.0.0.1'); + assert.deepStrictEqual(cfg.port, 5555); + assert.deepStrictEqual(cfg.database, 'any db'); + assert.deepStrictEqual(cfg.password, '1234'); + assert.deepStrictEqual(cfg.user, 'me'); + }); + + }); + + describe('Get connection config from environment variables', function () { + process.env.PGHOST = 'PGHOST'; + process.env.PGPORT = '1234'; + process.env.PGDATABASE = 'PGDATABASE'; + process.env.PGUSER = 'PGUSER'; + process.env.PGPASSWORD = 'PGPASSWORD'; + process.env.PGAPPNAME = 'PGAPPNAME'; + process.env.PGCONNECT_TIMEOUT = '32000'; + const cfg = getConnectionConfig(); + assert.strictEqual(cfg.host, 'pghost'); + assert.strictEqual(cfg.port, 1234); + assert.strictEqual(cfg.database, 'PGDATABASE'); + assert.strictEqual(cfg.user, 'PGUSER'); + assert.strictEqual(cfg.password, 'PGPASSWORD'); + assert.strictEqual(cfg.applicationName, 'PGAPPNAME'); + assert.strictEqual(cfg.connectTimeoutMs, 32000); + }); + +}); diff --git a/test/A-helpers/parse-connection-string.spec.ts b/test/A-helpers/parse-connection-string.spec.ts deleted file mode 100644 index 0d71b6a..0000000 --- a/test/A-helpers/parse-connection-string.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import assert from 'assert'; -import '../_support/env'; -import {parseConnectionString} from '../../src/helpers/parse-connectionstring'; - -describe('Parse connection string', function () { - - it('should parse simple unix sockets strings', function () { - const cfg = parseConnectionString('/var/run/ anydb'); - assert.deepStrictEqual(cfg.host, '/var/run/'); - assert.deepStrictEqual(cfg.database, 'anydb'); - }); - - it('should parse unix sockets strings', function () { - const cfg = parseConnectionString('socket://some path/?db=any%2bdb'); - assert.deepStrictEqual(cfg.host, '/some path/'); - assert.deepStrictEqual(cfg.database, 'any+db'); - }); - - it('should parse unix with auth', function () { - let cfg = parseConnectionString('socket://me:1234@some path/?db=any db'); - assert.deepStrictEqual(cfg.host, '/some path/'); - assert.deepStrictEqual(cfg.database, 'any db'); - assert.deepStrictEqual(cfg.password, '1234'); - assert.deepStrictEqual(cfg.user, 'me'); - }); - - it('should parse url', function () { - let cfg = parseConnectionString('postgres://me:1234@localhost/any db'); - assert.deepStrictEqual(cfg.host, 'localhost'); - assert.deepStrictEqual(cfg.database, 'any db'); - assert.deepStrictEqual(cfg.password, '1234'); - assert.deepStrictEqual(cfg.user, 'me'); - }); - - it('should get host from query', function () { - let cfg = parseConnectionString('postgres://me:1234@:5555/any db?host=127.0.0.1'); - assert.deepStrictEqual(cfg.host, '127.0.0.1'); - assert.deepStrictEqual(cfg.port, 5555); - assert.deepStrictEqual(cfg.database, 'any db'); - assert.deepStrictEqual(cfg.password, '1234'); - assert.deepStrictEqual(cfg.user, 'me'); - }); - -}); diff --git a/test/B-connection/connect-close.spec.ts b/test/B-connection/01-connection.spec.ts similarity index 56% rename from test/B-connection/connect-close.spec.ts rename to test/B-connection/01-connection.spec.ts index c64a71b..be48dc2 100644 --- a/test/B-connection/connect-close.spec.ts +++ b/test/B-connection/01-connection.spec.ts @@ -3,16 +3,45 @@ import net from "net"; import '../_support/env'; import {Connection, ConnectionState, ScriptExecutor} from '../../src'; -describe('Connect & Close', function () { +describe('Connection', function () { + + let connection: Connection; after(async () => { if (connection) await connection.close(0); }) - let connection: Connection; + + it('should connect', async function () { + connection = new Connection(); + await connection.connect(); + assert.strictEqual(connection.state, ConnectionState.READY); + }); + + it('should execute simple query', async function () { + const result = await connection.execute(`select 1`); + assert.ok(result); + assert.strictEqual(result.totalCommands, 1); + assert.strictEqual(result.results.length, 1); + assert.strictEqual(result.results[0].command, 'SELECT'); + }); + + it('should execute extended query', async function () { + const result = await connection.query(`select $1`, {params: [1234]}); + assert.ok(result); + assert.ok(result.fields); + assert.ok(result.rows); + assert.strictEqual(result.command, 'SELECT'); + assert.strictEqual(result.rows[0][0], 1234); + }); + + it('should close', async function () { + await connection.close(0); + assert.strictEqual(connection.state, ConnectionState.CLOSED); + }); it('should emit "connecting" and "ready" events while connect', async function () { - connection = new Connection(process.env.DB_URL); + connection = new Connection(); const events = []; connection.on('connecting', () => events.push('connecting')); connection.on('ready', () => events.push('ready')); @@ -20,9 +49,12 @@ describe('Connect & Close', function () { assert.ok(events.includes('connecting'), 'connecting event is not called'); assert.ok(events.includes('ready'), 'ready event is not called'); assert.strictEqual(connection.state, ConnectionState.READY); + await connection.close(0); }); it('should emit "close" event while close', async function () { + connection = new Connection(); + await connection.connect(); const events = []; connection.on('close', () => events.push('close')); await connection.close(); @@ -31,13 +63,13 @@ describe('Connect & Close', function () { }); it('should wait for active query before terminate', async function () { - const connection1 = new Connection(process.env.DB_URL); - await connection1.connect(); + connection = new Connection(process.env.PGHOST); + await connection.connect(); let terminated = false; const startTime = Date.now(); - connection1.on('terminate', () => terminated = true); - connection1['_activeQuery'] = new ScriptExecutor(connection1); - await connection1.close(500); + connection.on('terminate', () => terminated = true); + connection['_activeQuery'] = new ScriptExecutor(connection); + await connection.close(500); assert.strictEqual(terminated, true); assert.ok(Date.now() - startTime >= 500); }); diff --git a/test/B-connection/02-pool.spec.ts b/test/B-connection/02-pool.spec.ts new file mode 100644 index 0000000..2bcfe9d --- /dev/null +++ b/test/B-connection/02-pool.spec.ts @@ -0,0 +1,69 @@ +import assert from 'assert'; +import '../_support/env'; +import {DataTypeOIDs, Pool} from '../../src'; + +describe('Pool', function () { + + let pool: Pool; + + before(async () => { + pool = new Pool(); + }) + + after(async () => { + if (pool) + await pool.close(0); + }) + + it('should acquire connection', async function () { + assert.strictEqual(pool.totalConnections, 0); + const connection = await pool.acquire(); + assert.strictEqual(pool.totalConnections, 1); + assert.strictEqual(pool.acquiredConnections, 1); + assert.ok(connection); + await connection.release(); + assert.strictEqual(pool.acquiredConnections, 0); + }); + + it('should execute simple query', async function () { + const result = await pool.execute(`select 1`); + assert.strictEqual(pool.acquiredConnections, 0); + assert.ok(result); + assert.strictEqual(result.totalCommands, 1); + assert.strictEqual(result.results.length, 1); + assert.strictEqual(result.results[0].command, 'SELECT'); + }); + + it('should create a prepared statement, execute and release connection', async function () { + const statement = await pool.prepare(`select $1`, {paramTypes: [DataTypeOIDs.Int4]}); + assert.strictEqual(pool.acquiredConnections, 1); + assert.ok(statement); + const result = await statement.execute({params: [1234]}); + assert.strictEqual(pool.acquiredConnections, 1); + assert.ok(result); + assert.strictEqual(result.rows[0][0], 1234); + await new Promise((resolve, reject) => { + pool.once('release', resolve); + statement.close().catch(reject); + }); + assert.strictEqual(pool.acquiredConnections, 0); + }); + + it('should execute extended query', async function () { + const result = await pool.query(`select $1`, {params: [1234]}); + assert.strictEqual(pool.acquiredConnections, 0); + assert.ok(result); + assert.ok(result.fields); + assert.ok(result.rows); + assert.strictEqual(result.command, 'SELECT'); + assert.strictEqual(result.rows[0][0], 1234); + }); + + it('should close all connections and shutdown pool', async function () { + assert.strictEqual(pool.totalConnections, 1); + assert.strictEqual(pool.acquiredConnections, 0); + await pool.close(); + assert.strictEqual(pool.totalConnections, 0); + }); + +}); diff --git a/test/B-connection/execute-script.spec.ts b/test/B-connection/03-execute-script.spec.ts similarity index 95% rename from test/B-connection/execute-script.spec.ts rename to test/B-connection/03-execute-script.spec.ts index 5d7847d..c195126 100644 --- a/test/B-connection/execute-script.spec.ts +++ b/test/B-connection/03-execute-script.spec.ts @@ -1,14 +1,14 @@ import assert from 'assert'; import '../_support/env'; import {Connection} from '../../src'; -import {createTestSchema, fillTestSchema} from '../_support/createdb'; +import {createTestSchema} from '../_support/createdb'; describe('Execute script (Simple Query)', function () { let connection: Connection; before(async () => { - connection = new Connection(process.env.DB_URL); + connection = new Connection(); await connection.connect(); }) @@ -110,10 +110,6 @@ describe('Execute script (Simple Query)', function () { assert.deepStrictEqual(row.f_box, {x1: 4.6, y1: 3, x2: -1.6, y2: 0.1}); }); - it('fill test schema', async function () { - await fillTestSchema(connection); - }); - it('should return all rows', async function () { const result = await connection.execute(`select * from test.regions`, {objectRows: true}); diff --git a/test/B-connection/04-query.spec.ts b/test/B-connection/04-query.spec.ts new file mode 100644 index 0000000..2d67e80 --- /dev/null +++ b/test/B-connection/04-query.spec.ts @@ -0,0 +1,70 @@ +import assert from 'assert'; +import '../_support/env'; +import {Connection} from '../../src'; +import {createTestSchema} from '../_support/createdb'; +import {Cursor} from '../../src/Cursor'; + +describe('Query (Extended Query)', function () { + + let connection: Connection; + + before(async () => { + connection = new Connection(); + await connection.connect(); + await createTestSchema(connection); + }) + + after(async () => { + await connection.close(0); + }) + + it('should query return QueryResult', async function () { + const result = await connection.query(`select * from test.regions`); + assert.ok(result); + assert.ok(result.fields); + assert.ok(result.rows); + assert.notStrictEqual(result.executeTime, undefined); + assert.strictEqual(result.command, 'SELECT'); + assert.strictEqual(result.fields[0].fieldName, 'id'); + assert.strictEqual(result.fields[1].fieldName, 'name'); + assert.strictEqual(result.rows[0][0], 'US'); + assert.strictEqual(result.rows[0][1], 'US Region'); + }); + + it('should query return object rows', async function () { + const result = await connection.query(`select * from test.regions order by ID desc`, + {objectRows: true}); + assert.ok(result); + assert.strictEqual(result.command, 'SELECT'); + assert.strictEqual(result.fields[0].fieldName, 'id'); + assert.strictEqual(result.fields[1].fieldName, 'name'); + assert.strictEqual(result.rows[0].id, 'US'); + assert.strictEqual(result.rows[0].name, 'US Region'); + }); + + it('should limit number of returning rows with "fetchCount" property', async function () { + const result = await connection.query(`select * from test.airports`, + {fetchCount: 10}); + assert.ok(result); + assert.strictEqual(result.command, 'SELECT'); + assert.strictEqual(result.rows.length, 10); + }); + + it('should use bind parameters', async function () { + const result = await connection.query(`select * from test.airports where id=$1`, + {params: ['ARGNT'], objectRows: true}); + assert.ok(result); + assert.strictEqual(result.command, 'SELECT'); + assert.strictEqual(result.rows.length, 1); + assert.strictEqual(result.rows[0].id, 'ARGNT'); + }); + + it('should return cursor', async function () { + const result = await connection.query(`select * from test.airports`, + {objectRows: true, cursor: true}); + assert.ok(result); + assert.ok(result.cursor); + assert.ok(result.cursor instanceof Cursor); + }); + +}); diff --git a/test/B-connection/datatypes.spec.ts b/test/B-connection/05-datatypes.spec.ts similarity index 98% rename from test/B-connection/datatypes.spec.ts rename to test/B-connection/05-datatypes.spec.ts index cc2f12f..89c9a4c 100644 --- a/test/B-connection/datatypes.spec.ts +++ b/test/B-connection/05-datatypes.spec.ts @@ -3,11 +3,11 @@ import '../_support/env'; import { Connection, BindParam, - DataTypeOIDs, - DataTypeRegistry, - FetchOptions, + GlobalTypeMap, + DataMappingOptions, escapeLiteral, - stringifyValueForSQL + stringifyValueForSQL, + DataTypeOIDs } from '../../src'; import {Protocol} from '../../src/protocol/protocol'; @@ -16,10 +16,10 @@ import DataFormat = Protocol.DataFormat; describe('Data type encode/decode', function () { let connection: Connection; - process.env.TZ = 'Europe/Istanbul'; + process.env.PGTZ = 'Europe/Istanbul'; before(async () => { - connection = new Connection(process.env.DB_URL); + connection = new Connection(); await connection.connect(); await connection.execute('SET SESSION timezone TO \'Europe/Berlin\''); }) @@ -31,24 +31,24 @@ describe('Data type encode/decode', function () { async function parseTest(dataTypeId: number, input: any[], output: any[], opts: { columnFormat: DataFormat }, - fetchOpts?: FetchOptions) { - const reg = DataTypeRegistry.items[dataTypeId]; + mappingOptions?: DataMappingOptions) { + const reg = GlobalTypeMap.get(dataTypeId); if (!reg) throw new Error(`Data type "${dataTypeId}" is not registered.`); const typeName = reg.name; let sql; - if (reg.isArray) { - const s = stringifyValueForSQL(input, opts); + if (reg.elementsOID) { + const s = stringifyValueForSQL(input, mappingOptions); sql = `select ${s}::${typeName} as f1`; } else { const inp = input.map(escapeLiteral); sql = 'select ' + inp.map((x: string, i: number) => `${x}::${typeName} as f${i + 1}`) .join(', '); } - const resp = await connection.query(sql, {...fetchOpts, columnFormat: opts.columnFormat}); + const resp = await connection.query(sql, {...mappingOptions, columnFormat: opts.columnFormat}); assert.ok(resp && resp.rows); - if (reg.isArray) + if (reg.elementsOID) assert.deepStrictEqual(resp.rows[0][0], output); else for (const [i, v] of output.entries()) { @@ -57,13 +57,13 @@ describe('Data type encode/decode', function () { } async function encodeTest(dataTypeId: number, input: any[], output?: any[], - fetchOpts?: FetchOptions) { - const reg = DataTypeRegistry.items[dataTypeId]; + mappingOptions?: DataMappingOptions) { + const reg = GlobalTypeMap.get(dataTypeId); if (!reg) throw new Error(`Data type "0x${dataTypeId.toString(16)}" is not registered.`); let sql; let params; - if (reg.isArray) { + if (reg.elementsOID) { sql = 'select $1 as f1'; params = [new BindParam(dataTypeId, input)]; } else { @@ -72,10 +72,10 @@ describe('Data type encode/decode', function () { .join(', '); params = input.map(v => new BindParam(dataTypeId, v)); } - const resp = await connection.query(sql, {...fetchOpts, params}); + const resp = await connection.query(sql, {...mappingOptions, params}); assert.ok(resp && resp.rows); output = output === undefined ? input : output; - if (reg.isArray) + if (reg.elementsOID) assert.deepStrictEqual(resp.rows[0][0], output); else for (const [i, v] of output.entries()) { diff --git a/test/B-connection/06-cursor.spec.ts b/test/B-connection/06-cursor.spec.ts new file mode 100644 index 0000000..96a831b --- /dev/null +++ b/test/B-connection/06-cursor.spec.ts @@ -0,0 +1,77 @@ +import assert from 'assert'; +import '../_support/env'; +import {Connection} from '../../src'; +import {createTestSchema} from '../_support/createdb'; + +describe('Cursor support', function () { + + let connection: Connection; + + before(async () => { + connection = new Connection(); + await connection.connect(); + await createTestSchema(connection); + }) + + after(async () => { + await connection.close(0); + }) + + it('should fetch rows', async function () { + const result = await connection.query(`select * from test.airports order by id`, + {objectRows: false, cursor: true}); + const cursor = result.cursor; + assert.ok(cursor); + const row = await cursor.next(); + assert.deepStrictEqual(row[0], 'AIGRE'); + await cursor.close(); + }); + + it('should fetch rows as object', async function () { + const result = await connection.query(`select * from test.airports order by id`, + {objectRows: true, cursor: true}); + const cursor = result.cursor; + assert.ok(cursor); + const row = await cursor.next(); + assert.deepStrictEqual(row.id, 'AIGRE'); + await cursor.close(); + }); + + it('should automatically close cursor after fetching all rows', async function () { + const result = await connection.query(`select * from test.airports limit 10`, + {objectRows: true, cursor: true}); + const cursor = result.cursor; + assert.ok(cursor); + let closed = false; + cursor.on('close', () => closed = true); + while (await cursor.next()) { + } + assert.strictEqual(closed, true); + }); + + it('should emit "close" event', async function () { + const result = await connection.query(`select * from test.airports order by id`, + {objectRows: true, cursor: true}); + const cursor = result.cursor; + assert.ok(cursor); + let closed = false; + cursor.on('close', () => closed = true); + await cursor.next(); + await cursor.close(); + assert.strictEqual(closed, true); + }); + + it('should emit "fetch" event', async function () { + const result = await connection.query(`select * from test.airports limit 10`, + {objectRows: true, cursor: true}); + const cursor = result.cursor; + assert.ok(cursor); + let count = 0; + cursor.on('fetch', (rows) => count += rows.length); + await cursor.next(); + await cursor.close(); + assert.strictEqual(count, 10); + }); + + +}); diff --git a/test/B-connection/query.spec.ts b/test/B-connection/query.spec.ts deleted file mode 100644 index c0fb3ec..0000000 --- a/test/B-connection/query.spec.ts +++ /dev/null @@ -1,50 +0,0 @@ -import assert from 'assert'; -import '../_support/env'; -import {Connection} from '../../src'; - -describe('Query (Extended Query)', function () { - - let connection: Connection; - - before(async () => { - connection = new Connection(process.env.DB_URL); - await connection.connect(); - }) - - after(async () => { - await connection.close(0); - }) - - it('should query return QueryResult', async function () { - const result = await connection.query(`select 1 as f1`); - assert.ok(result); - assert.ok(result.fields); - assert.ok(result.rows); - assert.notStrictEqual(result.prepareTime, undefined); - assert.notStrictEqual(result.executeTime, undefined); - assert.notStrictEqual(result.totalTime, undefined); - assert.strictEqual(result.command, 'SELECT'); - assert.strictEqual(result.fields[0].fieldName, 'f1'); - assert.strictEqual(result.rows[0][0], 1); - }); - - it('should query return object rows', async function () { - const result = await connection.query(`select 1 as f1, 'two'::varchar as f2 `, - {objectRows: true}); - assert.ok(result); - assert.strictEqual(result.command, 'SELECT'); - assert.strictEqual(result.fields[0].fieldName, 'f1'); - assert.strictEqual(result.fields[1].fieldName, 'f2'); - assert.strictEqual(result.rows[0].f1, 1); - assert.strictEqual(result.rows[0].f2, 'two'); - }); - - it('should "fetchCount" property limit number of returning rows', async function () { - const result = await connection.query(`SELECT a.n from generate_series(1, 20) as a(n)`, - {fetchCount: 10}); - assert.ok(result); - assert.strictEqual(result.command, 'SELECT'); - assert.strictEqual(result.rows.length, 10); - }); - -}); diff --git a/test/_support/createdb.sql b/test/_support/createdb.sql index 0e09773..b3dc1b0 100644 --- a/test/_support/createdb.sql +++ b/test/_support/createdb.sql @@ -5,7 +5,6 @@ CREATE TABLE test.regions ( id character varying(10) NOT NULL, name character varying(16), - tags character varying(16)[], CONSTRAINT regions_pkey PRIMARY KEY (id) ); diff --git a/test/_support/createdb.ts b/test/_support/createdb.ts index 47c0284..3077329 100644 --- a/test/_support/createdb.ts +++ b/test/_support/createdb.ts @@ -1,10 +1,9 @@ import * as fs from 'fs'; import * as path from 'path'; import {Connection} from '../../src'; -import {stringifyValueForSQL} from '../../src/helpers/stringify-for-sql'; +import {stringifyValueForSQL} from '../../src'; let testDbCreated = false; -let testDbFilled = false; const structureScript = fs.readFileSync(path.join(__dirname, 'createdb.sql'), 'utf8'); const dataFiles: any[] = [ JSON.parse(fs.readFileSync(path.join(__dirname, 'test-data', 'regions.json'), 'utf8')), @@ -15,13 +14,6 @@ export async function createTestSchema(connection: Connection) { if (testDbCreated) return; await connection.execute(structureScript); - testDbCreated = true; -} - -export async function fillTestSchema(connection: Connection) { - if (testDbFilled) - return; - /* Create tables */ for (const table of dataFiles) { /* Insert rows */ @@ -36,5 +28,5 @@ export async function fillTestSchema(connection: Connection) { } await connection.execute(sql); } - testDbFilled = true; + testDbCreated = true; } diff --git a/test/_support/db_config.json b/test/_support/db_config.json deleted file mode 100644 index 9eef59c..0000000 --- a/test/_support/db_config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "url": "postgres://postgres:postgres@localhost/test?schema=sqbtest", - "skip_create_tables": true -} diff --git a/test/_support/env.ts b/test/_support/env.ts index 36a0e25..403915f 100644 --- a/test/_support/env.ts +++ b/test/_support/env.ts @@ -1,12 +1,5 @@ -import * as fs from 'fs'; -import * as path from 'path'; +import dotenv from 'dotenv'; -process.env.NODE_ENV = 'test'; +dotenv.config({path: __dirname + '/.env'}); -const f = path.join(__dirname, 'db_config.json'); -if (fs.existsSync(f)) { - const config = require(f); - process.env.DB_URL = process.env.DB_URL || config.url; - if (process.env.SKIP_CREATE_TABLES || config.skip_create_tables) - process.env.SKIP_CREATE_TABLES = 'true'; -} +process.env.NODE_ENV = 'test'; diff --git a/test/_support/test-data/regions.json b/test/_support/test-data/regions.json index 6e99259..ec0fdf0 100644 --- a/test/_support/test-data/regions.json +++ b/test/_support/test-data/regions.json @@ -2,32 +2,20 @@ "name": "regions", "rows": [ { - "id": "FR", - "name": "FR Region", - "tags": [ - "a1", - "b2" - ] + "id": "US", + "name": "US Region" }, { "id": "TR", - "name": "TR Region", - "tags": [ - "c3", - "d4" - ] + "name": "TR Region" }, { "id": "GB", - "name": "GB Region", - "tags": [ - "e5", - "f6" - ] + "name": "GB Region" }, { - "id": "US", - "name": "US Region" + "id": "FR", + "name": "FR Region" }, { "id": "CN",