From d4e2e5539e546769387a7b04fd1ad9552fede331 Mon Sep 17 00:00:00 2001 From: Yi Lyu <41231856+isabella0428@users.noreply.github.com> Date: Wed, 22 Jul 2020 17:44:03 +0800 Subject: [PATCH 01/57] [Table] Project Setup 1 (#479) * [Table] Init commit - generated from swagger * Add table draft * Finish create table * Fix tslint error * Fix windows tslint error * Fix comment and code details * Fix bugs * Remove unnecessary log * Remove certificate file Co-authored-by: Xiaoning Liu --- .gitignore | 3 +- package-lock.json | 40 +- package.json | 9 +- src/azurite.ts | 51 +- src/common/Environment.ts | 25 + src/table/ITableEnvironment.ts | 21 + src/table/TableConfiguration.ts | 54 + src/table/TableEnvironment.ts | 101 + src/table/TableRequestListenerFactory.ts | 82 + src/table/TableServer.ts | 107 + src/table/context/TableStorageContext.ts | 35 + src/table/errors/NotImplementedError.ts | 19 + src/table/errors/StorageError.ts | 67 + src/table/errors/StorageErrorFactory.ts | 45 + src/table/generated/Context.ts | 144 ++ .../generated/ExpressMiddlewareFactory.ts | 161 ++ src/table/generated/ExpressRequestAdapter.ts | 57 + src/table/generated/ExpressResponseAdapter.ts | 62 + src/table/generated/IRequest.ts | 25 + src/table/generated/IResponse.ts | 16 + src/table/generated/MiddlewareFactory.ts | 91 + src/table/generated/artifacts/mappers.ts | 1168 ++++++++++ src/table/generated/artifacts/models.ts | 1470 +++++++++++++ src/table/generated/artifacts/operation.ts | 25 + src/table/generated/artifacts/parameters.ts | 278 +++ .../generated/artifacts/specifications.ts | 558 +++++ .../generated/errors/DeserializationError.ts | 8 + src/table/generated/errors/MiddlewareError.ts | 29 + .../errors/OperationMismatchError.ts | 11 + .../errors/UnsupportedRequestError.ts | 11 + src/table/generated/handlers/IHandlers.ts | 9 + .../generated/handlers/IServiceHandler.ts | 19 + src/table/generated/handlers/ITableHandler.ts | 27 + .../generated/handlers/handlerMappers.ts | 134 ++ .../middleware/HandlerMiddlewareFactory.ts | 90 + .../middleware/deserializer.middleware.ts | 59 + .../middleware/dispatch.middleware.ts | 176 ++ .../generated/middleware/end.middleware.ts | 32 + .../generated/middleware/error.middleware.ts | 134 ++ .../middleware/serializer.middleware.ts | 57 + src/table/generated/utils/ILogger.ts | 13 + src/table/generated/utils/serializer.ts | 353 +++ src/table/generated/utils/utils.ts | 20 + src/table/generated/utils/xml.ts | 41 + src/table/handlers/BaseHandler.ts | 17 + src/table/handlers/ServiceHandler.ts | 33 + src/table/handlers/TableHandler.ts | 185 ++ src/table/main.ts | 85 + .../tableStorageContext.middleware.ts | 109 + src/table/persistence/ITableMetadataStore.ts | 64 + .../persistence/LokiTableMetadataStore.ts | 188 ++ src/table/utils/constants.ts | 25 + swagger/table.md | 69 + swagger/table/examples/TableCreate.json | 22 + swagger/table/examples/TableDelete.json | 10 + swagger/table/examples/TableDeleteEntity.json | 14 + swagger/table/examples/TableGet.json | 23 + swagger/table/examples/TableInsertEntity.json | 48 + swagger/table/examples/TableMergeEntity.json | 27 + .../table/examples/TableQueryEntities.json | 30 + ...leQueryEntitiesWithPartitionAndRowKey.json | 31 + swagger/table/examples/TableUpdateEntity.json | 27 + swagger/table/table.json | 1913 +++++++++++++++++ tests/table/apis/table.test.ts | 20 + 64 files changed, 8855 insertions(+), 22 deletions(-) create mode 100644 src/table/ITableEnvironment.ts create mode 100644 src/table/TableConfiguration.ts create mode 100644 src/table/TableEnvironment.ts create mode 100644 src/table/TableRequestListenerFactory.ts create mode 100644 src/table/TableServer.ts create mode 100644 src/table/context/TableStorageContext.ts create mode 100644 src/table/errors/NotImplementedError.ts create mode 100644 src/table/errors/StorageError.ts create mode 100644 src/table/errors/StorageErrorFactory.ts create mode 100644 src/table/generated/Context.ts create mode 100644 src/table/generated/ExpressMiddlewareFactory.ts create mode 100644 src/table/generated/ExpressRequestAdapter.ts create mode 100644 src/table/generated/ExpressResponseAdapter.ts create mode 100644 src/table/generated/IRequest.ts create mode 100644 src/table/generated/IResponse.ts create mode 100644 src/table/generated/MiddlewareFactory.ts create mode 100644 src/table/generated/artifacts/mappers.ts create mode 100644 src/table/generated/artifacts/models.ts create mode 100644 src/table/generated/artifacts/operation.ts create mode 100644 src/table/generated/artifacts/parameters.ts create mode 100644 src/table/generated/artifacts/specifications.ts create mode 100644 src/table/generated/errors/DeserializationError.ts create mode 100644 src/table/generated/errors/MiddlewareError.ts create mode 100644 src/table/generated/errors/OperationMismatchError.ts create mode 100644 src/table/generated/errors/UnsupportedRequestError.ts create mode 100644 src/table/generated/handlers/IHandlers.ts create mode 100644 src/table/generated/handlers/IServiceHandler.ts create mode 100644 src/table/generated/handlers/ITableHandler.ts create mode 100644 src/table/generated/handlers/handlerMappers.ts create mode 100644 src/table/generated/middleware/HandlerMiddlewareFactory.ts create mode 100644 src/table/generated/middleware/deserializer.middleware.ts create mode 100644 src/table/generated/middleware/dispatch.middleware.ts create mode 100644 src/table/generated/middleware/end.middleware.ts create mode 100644 src/table/generated/middleware/error.middleware.ts create mode 100644 src/table/generated/middleware/serializer.middleware.ts create mode 100644 src/table/generated/utils/ILogger.ts create mode 100644 src/table/generated/utils/serializer.ts create mode 100644 src/table/generated/utils/utils.ts create mode 100644 src/table/generated/utils/xml.ts create mode 100644 src/table/handlers/BaseHandler.ts create mode 100644 src/table/handlers/ServiceHandler.ts create mode 100644 src/table/handlers/TableHandler.ts create mode 100644 src/table/main.ts create mode 100644 src/table/middleware/tableStorageContext.middleware.ts create mode 100644 src/table/persistence/ITableMetadataStore.ts create mode 100644 src/table/persistence/LokiTableMetadataStore.ts create mode 100644 src/table/utils/constants.ts create mode 100644 swagger/table.md create mode 100644 swagger/table/examples/TableCreate.json create mode 100644 swagger/table/examples/TableDelete.json create mode 100644 swagger/table/examples/TableDeleteEntity.json create mode 100644 swagger/table/examples/TableGet.json create mode 100644 swagger/table/examples/TableInsertEntity.json create mode 100644 swagger/table/examples/TableMergeEntity.json create mode 100644 swagger/table/examples/TableQueryEntities.json create mode 100644 swagger/table/examples/TableQueryEntitiesWithPartitionAndRowKey.json create mode 100644 swagger/table/examples/TableUpdateEntity.json create mode 100644 swagger/table/table.json create mode 100644 tests/table/apis/table.test.ts diff --git a/.gitignore b/.gitignore index aa60b964d..7db1cbad8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ debug.log *.tgz __* *.env -temp \ No newline at end of file +temp +**/.DS_Store.DS_Store diff --git a/package-lock.json b/package-lock.json index 97c02cba9..a881ebd00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -136,22 +136,28 @@ } }, "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "^7.10.4" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -637,9 +643,9 @@ "dev": true }, "autorest": { - "version": "2.0.4283", - "resolved": "https://registry.npmjs.org/autorest/-/autorest-2.0.4283.tgz", - "integrity": "sha512-3jU9yDR71d2thRnKdPH03DaWbla1Iqnrx2rqUUwbMrb4di36a8+nttCQaTWG7biWPJc6Ke6zSSTzFH0uhya+Nw==", + "version": "2.0.4413", + "resolved": "https://registry.npmjs.org/autorest/-/autorest-2.0.4413.tgz", + "integrity": "sha512-Ttx/O6Yag5q8fpJDvllgf/joLuVPBySkbAqDF7+9jAmscCPQplYjA9H/N12bwkhh+6YR3ugWZHQq3NTN33hkAg==", "dev": true }, "aws-sign2": { @@ -6087,9 +6093,9 @@ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" }, "tslint": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.0.tgz", - "integrity": "sha512-2vqIvkMHbnx8acMogAERQ/IuINOq6DFqgF8/VDvhEkBqQh/x6SP0Y+OHnKth9/ZcHQSroOZwUQSN18v8KKF0/g==", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -6108,9 +6114,9 @@ }, "dependencies": { "diff": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", - "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, "semver": { diff --git a/package.json b/package.json index dfd4e9343..25c6593b5 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "bin": { "azurite": "./dist/src/azurite.js", "azurite-blob": "./dist/src/blob/main.js", - "azurite-queue": "./dist/src/queue/main.js" + "azurite-queue": "./dist/src/queue/main.js", + "azurite-table": "./dist/src/table/main.js" }, "engines": { "node": ">=8.0.0", @@ -57,7 +58,7 @@ "@types/validator": "^10.11.3", "@types/vscode": "^1.39.0", "@types/xml2js": "^0.4.3", - "autorest": "^2.0.4283", + "autorest": "^2.0.4413", "cross-env": "^6.0.3", "cross-var": "^1.1.0", "husky": "^1.3.1", @@ -66,7 +67,7 @@ "prettier": "^1.16.4", "prettier-tslint": "^0.4.2", "ts-node": "^7.0.1", - "tslint": "^5.16.0", + "tslint": "^5.20.1", "typescript": "^3.1.4", "vsce": "^1.64.0" }, @@ -215,6 +216,7 @@ "build:autorest:debug": "autorest ./swagger/blob.md --typescript --typescript.debugger --use=E:/GitHub/XiaoningLiu/autorest.typescript.server", "build:autorest:blob": "autorest ./swagger/blob.md --typescript --use=S:/GitHub/XiaoningLiu/autorest.typescript.server", "build:autorest:queue": "autorest ./swagger/queue.md --typescript --use=S:/GitHub/XiaoningLiu/autorest.typescript.server", + "build:autorest:table": "autorest ./swagger/table.md --typescript --use=/Users/isabella/Desktop/AzureStorage/autorest.typescript.server", "watch": "tsc -watch -p ./", "blob": "node -r ts-node/register src/blob/main.ts", "queue": "node -r ts-node/register src/queue/main.ts", @@ -225,6 +227,7 @@ "test:blob:sql": "npm run lint && cross-env cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 AZURITE_TEST_DB=mysql://root:my-secret-pw@127.0.0.1:3306/azurite_blob_test mocha --compilers ts-node/register --no-timeouts --grep @sql --recursive tests/blob/*.test.ts tests/blob/**/*.test.ts", "test:blob:sql:ci": "npm run lint && cross-env cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 AZURITE_TEST_DB=mysql://root:my-secret-pw@127.0.0.1:13306/azurite_blob_test mocha --compilers ts-node/register --no-timeouts --grep @sql --recursive tests/blob/*.test.ts tests/blob/**/*.test.ts", "test:queue": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/queue/*.test.ts tests/queue/**/*.test.ts", + "test:table": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/table/*.test.ts tests/table/**/*.test.ts", "clean": "rimraf dist typings *.log coverage __testspersistence__ temp __testsstorage__ .nyc_output debug.log *.vsix *.tgz", "clean:deep": "npm run clean && rimraf debug.log __*", "validate:npmpack:win": "npm install && npm run build && npm pack && cross-var npm install -g azurite-$npm_package_version.tgz && azurite -v && azurite-blob -v && azurite-queue -v", diff --git a/src/azurite.ts b/src/azurite.ts index 48b6a1ad9..269bb07c0 100644 --- a/src/azurite.ts +++ b/src/azurite.ts @@ -7,6 +7,7 @@ import { promisify } from "util"; import Environment from "./common/Environment"; // tslint:disable-next-line:ordered-imports import { BlobServerFactory } from "./blob/BlobServerFactory"; + import * as Logger from "./common/Logger"; import QueueConfiguration from "./queue/QueueConfiguration"; import QueueServer from "./queue/QueueServer"; @@ -17,6 +18,13 @@ import { DEFAULT_QUEUE_PERSISTENCE_PATH } from "./queue/utils/constants"; +import TableConfiguration from "./table/TableConfiguration"; +import TableServer from "./table/TableServer"; + +import { + DEFAULT_TABLE_LOKI_DB_PATH +} from "./table/utils/constants"; + // tslint:disable:no-console const accessAsync = promisify(access); @@ -46,6 +54,7 @@ async function main() { location, DEFAULT_QUEUE_PERSISTENCE_PATH ); + const queueConfig = new QueueConfiguration( env.queueHost(), env.queuePort(), @@ -64,15 +73,34 @@ async function main() { env.oauth() ); + const tableConfig = new TableConfiguration( + env.tableHost(), + env.tablePort(), + join(location, DEFAULT_TABLE_LOKI_DB_PATH), + !env.silent(), + undefined, + env.debug() !== undefined, + await env.debug(), + env.loose(), + env.skipApiVersionCheck(), + env.cert(), + env.key(), + env.pwd(), + env.oauth() + ); + // We use logger singleton as global debugger logger to track detailed outputs cross layers // Note that, debug log is different from access log which is only available in request handler layer to // track every request. Access log is not singleton, and initialized in specific RequestHandlerFactory implementations // Enable debug log by default before first release for debugging purpose Logger.configLogger(blobConfig.enableDebugLog, blobConfig.debugLogFilePath); - // Create server instance + // Create queue server instance const queueServer = new QueueServer(queueConfig); + // Create table server instance + const tableServer = new TableServer(tableConfig); + // Start server console.log( `Azurite Blob service is starting at ${blobConfig.getHttpServerAddress()}` @@ -91,9 +119,20 @@ async function main() { `Azurite Queue service is successfully listening at ${queueServer.getHttpServerAddress()}` ); + // Start server + console.log( + `Azurite Table service is starting at ${tableConfig.getHttpServerAddress()}` + ); + await tableServer.start(); + console.log( + `Azurite Table service is successfully listening at ${tableServer.getHttpServerAddress()}` + ); + // Handle close event const blobBeforeCloseMessage = `Azurite Blob service is closing...`; const blobAfterCloseMessage = `Azurite Blob service successfully closed`; + const tableBeforeCloseMessage = `Azurite Table service is closing...`; + const tableAfterCloseMessage = `Azurite Table service successfully closed`; const queueBeforeCloseMessage = `Azurite Queue service is closing...`; const queueAfterCloseMessage = `Azurite Queue service successfully closed`; process @@ -104,6 +143,11 @@ async function main() { console.log(blobAfterCloseMessage); }); + console.log(tableBeforeCloseMessage); + tableServer.close().then(() => { + console.log(tableAfterCloseMessage); + }); + console.log(queueBeforeCloseMessage); queueServer.close().then(() => { console.log(queueAfterCloseMessage); @@ -116,6 +160,11 @@ async function main() { console.log(blobAfterCloseMessage); }); + console.log(tableBeforeCloseMessage); + tableServer.close().then(() => { + console.log(tableAfterCloseMessage); + }); + console.log(queueBeforeCloseMessage); queueServer.close().then(() => { console.log(queueAfterCloseMessage); diff --git a/src/common/Environment.ts b/src/common/Environment.ts index 7368183fb..436a00a5d 100644 --- a/src/common/Environment.ts +++ b/src/common/Environment.ts @@ -4,10 +4,17 @@ import { DEFAULT_BLOB_LISTENING_PORT, DEFAULT_BLOB_SERVER_HOST_NAME } from "../blob/utils/constants"; + import { DEFAULT_QUEUE_LISTENING_PORT, DEFAULT_QUEUE_SERVER_HOST_NAME } from "../queue/utils/constants"; + +import { + DEFAULT_TABLE_LISTENING_PORT, + DEFAULT_TABLE_SERVER_HOST_NAME +} from "../table/utils/constants"; + import IEnvironment from "./IEnvironment"; args @@ -31,6 +38,16 @@ args "Optional. Customize listening port for queue", DEFAULT_QUEUE_LISTENING_PORT ) + .option( + ["", "tableHost"], + "Optional. Customize listening address for table", + DEFAULT_TABLE_SERVER_HOST_NAME + ) + .option( + ["", "tablePort"], + "Optional. Customize listening port for table", + DEFAULT_TABLE_LISTENING_PORT + ) .option( ["l", "location"], "Optional. Use an existing folder as workspace path, default is current working directory", @@ -75,6 +92,14 @@ export default class Environment implements IEnvironment { return this.flags.queuePort; } + public tableHost(): string | undefined { + return this.flags.tableHost; + } + + public tablePort(): number | undefined { + return this.flags.tablePort; + } + public async location(): Promise { return this.flags.location || process.cwd(); } diff --git a/src/table/ITableEnvironment.ts b/src/table/ITableEnvironment.ts new file mode 100644 index 000000000..d999ac497 --- /dev/null +++ b/src/table/ITableEnvironment.ts @@ -0,0 +1,21 @@ +/** + * This interface defines the required functions of TableEnvironment given command line parameter + * @export + * @interface ITableEnvironment + */ +export default interface ITableEnvironment { + /** Optional. Customize listening address for table */ + tableHost(): string | undefined; + /** Optional. Customize listening port for table */ + tablePort(): number | undefined; + /** Optional. Use an existing folder as workspace path, default is current working directory */ + location(): Promise; + /** Optional. Disable access log displayed in console */ + silent(): boolean; + /** Optional. Enable loose mode which ignores unsupported headers and parameters */ + loose(): boolean; + /** Optional. Skip the request API version check request with all Api versions will be allowed */ + skipApiVersionCheck(): boolean; + /** Optional. Enable debug log by providing a valid local file, path as log destination path as log destination */ + debug(): Promise; +} diff --git a/src/table/TableConfiguration.ts b/src/table/TableConfiguration.ts new file mode 100644 index 000000000..3c7c32f50 --- /dev/null +++ b/src/table/TableConfiguration.ts @@ -0,0 +1,54 @@ +import ConfigurationBase from "../common/ConfigurationBase"; +import { + DEFAULT_ENABLE_ACCESS_LOG, + DEFAULT_ENABLE_DEBUG_LOG, + DEFAULT_TABLE_LISTENING_PORT, + DEFAULT_TABLE_LOKI_DB_PATH, + DEFAULT_TABLE_SERVER_HOST_NAME +} from "./utils/constants"; + +/** + * Default configurations for default implementation of TableServer. + * + * As default implementation of TableServer class leverages LokiJS DB. + * This configuration class also maintains configuration settings for LokiJS DB. + * + * When creating other server implementations, should also create a NEW + * corresponding configuration class by extending ConfigurationBase. + * + * @export + * @class Configuration + */ + +export default class TableConfiguration extends ConfigurationBase { + public constructor( + host: string = DEFAULT_TABLE_SERVER_HOST_NAME, + port: number = DEFAULT_TABLE_LISTENING_PORT, + public readonly /* Store metadata */ metadataDBPath: string = DEFAULT_TABLE_LOKI_DB_PATH, + enableAccessLog: boolean = DEFAULT_ENABLE_ACCESS_LOG, + accessLogWriteStream?: NodeJS.WritableStream, + enableDebugLog: boolean = DEFAULT_ENABLE_DEBUG_LOG, + debugLogFilePath?: string, + loose: boolean = false, + skipApiVersionCheck: boolean = false, + cert: string = "", + key: string = "", + pwd: string = "", + oauth?: string + ) { + super( + host, + port, + enableAccessLog, + accessLogWriteStream, + enableDebugLog, + debugLogFilePath, + loose, + skipApiVersionCheck, + cert, + key, + pwd, + oauth + ); + } +} diff --git a/src/table/TableEnvironment.ts b/src/table/TableEnvironment.ts new file mode 100644 index 000000000..76b234341 --- /dev/null +++ b/src/table/TableEnvironment.ts @@ -0,0 +1,101 @@ +/** + * This file store table parameter from command line parameters + */ + +import args from "args"; +import ITableEnvironment from "./ITableEnvironment"; +import { + DEFAULT_TABLE_LISTENING_PORT, + DEFAULT_TABLE_SERVER_HOST_NAME +} from "./utils/constants"; + +args + .option( + ["", "tableHost"], + "Optional. Customize listening address for table", + DEFAULT_TABLE_SERVER_HOST_NAME + ) + .option( + ["", "tablePort"], + "Optional. Customize listening port for table", + DEFAULT_TABLE_LISTENING_PORT + ) + .option( + ["l", "location"], + "Optional. Use an existing folder as workspace path, default is current working directory", + process.cwd() + ) + .option(["s", "silent"], "Optional. Disable access log displayed in console") + .option( + ["L", "loose"], + "Optional. Enable loose mode which ignores unsupported headers and parameters" + ) + .option( + ["", "skipApiVersionCheck"], + "Optional. Skip the request API version check, request with all Api versions will be allowed" + ) + .option( + ["d", "debug"], + "Optional. Enable debug log by providing a valid local file path as log destination" + ); + +(args as any).config.name = "azurite-table"; + +/** + * This class store table configuration from command line parameters + * @export + * + */ +export default class TableEnvironment implements ITableEnvironment { + private flags = args.parse(process.argv); + + public tableHost(): string | undefined { + return this.flags.tableHost; + } + + public tablePort(): number | undefined { + return this.flags.tablePort; + } + + public async location(): Promise { + return this.flags.location || process.cwd(); + } + + public silent(): boolean { + if (this.flags.silent !== undefined) { + return true; + } + return false; + } + + public loose(): boolean { + if (this.flags.loose !== undefined) { + return true; + } + // default is false which will block not supported APIs, headers and parameters + return false; + } + + public skipApiVersionCheck(): boolean { + if (this.flags.skipApiVersionCheck !== undefined) { + return true; + } + // default is false which will check API veresion + return false; + } + + public async debug(): Promise { + if (typeof this.flags.debug === "string") { + // Enable debug log to file + return this.flags.debug; + } + + if (this.flags.debug === true) { + throw RangeError( + `Must provide a debug log file path for parameter -d or --debug` + ); + } + + // By default disable debug log + } +} diff --git a/src/table/TableRequestListenerFactory.ts b/src/table/TableRequestListenerFactory.ts new file mode 100644 index 000000000..fc9db3a1e --- /dev/null +++ b/src/table/TableRequestListenerFactory.ts @@ -0,0 +1,82 @@ +import express from "express"; +import { RequestListener } from "http"; + +import IRequestListenerFactory from "../common/IRequestListenerFactory"; +import logger from "../common/Logger"; +import ExpressMiddlewareFactory from "./generated/ExpressMiddlewareFactory"; +import IHandlers from "./generated/handlers/IHandlers"; +import MiddlewareFactory from "./generated/MiddlewareFactory"; +import ServiceHandler from "./handlers/ServiceHandler"; +import TableHandler from "./handlers/TableHandler"; +import createTableStorageContextMiddleware from "./middleware/tableStorageContext.middleware"; +import ITableMetadataStore from "./persistence/ITableMetadataStore"; +import { DEFAULT_TABLE_CONTEXT_PATH } from "./utils/constants"; + +import morgan = require("morgan"); +/** + * Default RequestListenerFactory based on express framework. + * + * When creating other server implementations, such as based on Koa. Should also create a NEW + * corresponding TableKoaRequestListenerFactory class by extending IRequestListenerFactory. + * + * @export + * @class TableRequestListenerFactory + * @implements {IRequestListenerFactory} + */ +export default class TableRequestListenerFactory + implements IRequestListenerFactory { + public constructor( + private readonly metadataStore: ITableMetadataStore, + private readonly enableAccessLog: boolean, + private readonly accessLogWriteStream?: NodeJS.WritableStream // private readonly skipApiVersionCheck?: boolean, + ) {} + + public createRequestListener(): RequestListener { + const app = express().disable("x-powered-by"); + + // MiddlewareFactory is a factory to create auto-generated middleware + const middlewareFactory: MiddlewareFactory = new ExpressMiddlewareFactory( + logger, + DEFAULT_TABLE_CONTEXT_PATH + ); + + // Create handlers into handler middleware factory + const handlers: IHandlers = { + tableHandler: new TableHandler(this.metadataStore, logger), + serviceHandler: new ServiceHandler(this.metadataStore, logger) + }; + + /* + * Generated middleware should follow strict orders + * Manually created middleware can be injected into any points + */ + + // Access log per request + if (this.enableAccessLog) { + app.use(morgan("common", { stream: this.accessLogWriteStream })); + } + + // Manually created middleware to deserialize feature related context which swagger doesn't know + app.use(createTableStorageContextMiddleware()); + + // Dispatch incoming HTTP request to specific operation + app.use(middlewareFactory.createDispatchMiddleware()); + + // Generated, will do basic validation defined in swagger + app.use(middlewareFactory.createDeserializerMiddleware()); + + // Generated, inject handlers to create a handler middleware + app.use(middlewareFactory.createHandlerMiddleware(handlers)); + + // Generated, will serialize response models into HTTP response + app.use(middlewareFactory.createSerializerMiddleware()); + + // Generated, will return MiddlewareError and Errors thrown in previous middleware/handlers to HTTP response + app.use(middlewareFactory.createErrorMiddleware()); + + // Generated, will end and return HTTP response immediately + app.use(middlewareFactory.createEndMiddleware()); + + return app; + } +} diff --git a/src/table/TableServer.ts b/src/table/TableServer.ts new file mode 100644 index 000000000..dfedc78f6 --- /dev/null +++ b/src/table/TableServer.ts @@ -0,0 +1,107 @@ +import * as http from "http"; +import * as https from "https"; + +import AccountDataStore from "../common/AccountDataStore"; +import { CertOptions } from "../common/ConfigurationBase"; +import IAccountDataStore from "../common/IAccountDataStore"; +import IRequestListenerFactory from "../common/IRequestListenerFactory"; +import logger from "../common/Logger"; +import ITableMetadataStore from "../table/persistence/ITableMetadataStore"; +import LokiTableMetadataStore from "../table/persistence/LokiTableMetadataStore"; + +import ServerBase from "../common/ServerBase"; +import TableConfiguration from "./TableConfiguration"; +import TableRequestListenerFactory from "./TableRequestListenerFactory"; + +/** + * Default implementation of Azurite Table HTTP server. + * This implementation provides a HTTP service based on express framework and LokiJS in memory database. + * + * We can create other table servers by extending abstract Server class and initialize different httpServer, + * dataStore or requestListenerFactory fields. + * + * For example, creating a HTTPS server to accept HTTPS requests, or using other + * Node.js HTTP frameworks like Koa, or just using another SQL database. + * + * @export + * @class Server + */ +export default class TableServer extends ServerBase { + private readonly /* Store the metadata of the table service */ metadataStore: ITableMetadataStore; + private readonly /* Store the account data */ accountDataStore: IAccountDataStore; + + constructor(configuration?: TableConfiguration) { + // If configuration is undefined, we'll use the default one + if (configuration === undefined) { + configuration = new TableConfiguration(); + } + + // Create a http server to accept table operation request + let httpServer; + const certOption = configuration.hasCert(); + switch (certOption) { + case CertOptions.PEM: + case CertOptions.PFX: + httpServer = https.createServer(configuration.getCert(certOption)!); + break; + default: + httpServer = http.createServer(); + } + + // Create **dataStore with Loki.js + const metadataStore: ITableMetadataStore = new LokiTableMetadataStore( + configuration.metadataDBPath + ); + const accountDataStore: IAccountDataStore = new AccountDataStore(logger); + + // Here we use express request listener and register table handler + const requestListenerFactory: IRequestListenerFactory = new TableRequestListenerFactory( + metadataStore, + configuration.enableAccessLog, // Access log includes every handled HTTP request + configuration.accessLogWriteStream + ); + + const host = configuration.host; + const port = configuration.port; + super(host, port, httpServer, requestListenerFactory, configuration); + + this.metadataStore = metadataStore; + this.accountDataStore = accountDataStore; + } + + protected async beforeStart(): Promise { + const msg = `Azurite Table service is starting on ${this.host}:${this.port}`; + logger.info(msg); + + if (this.accountDataStore !== undefined) { + await this.accountDataStore.init(); + } + + if (this.metadataStore !== undefined) { + await this.metadataStore.init(); + } + } + + protected async afterStart(): Promise { + const msg = `Azurite Table service successfully listens on ${this.getHttpServerAddress()}`; + logger.info(msg); + } + + protected async beforeClose(): Promise { + const BEFORE_CLOSE_MESSAGE = `Azurite Table service is closing...`; + logger.info(BEFORE_CLOSE_MESSAGE); + } + + protected async afterClose(): Promise { + if (this.metadataStore !== undefined) { + await this.metadataStore.close(); + } + + if (this.accountDataStore !== undefined) { + await this.accountDataStore.close(); + } + + const AFTER_CLOSE_MESSAGE = `Azurite Table service successfully closed`; + logger.info(AFTER_CLOSE_MESSAGE); + } +} diff --git a/src/table/context/TableStorageContext.ts b/src/table/context/TableStorageContext.ts new file mode 100644 index 000000000..659659660 --- /dev/null +++ b/src/table/context/TableStorageContext.ts @@ -0,0 +1,35 @@ +import Context from "../generated/Context"; + +export default class TableStorageContext extends Context { + public get account(): string | undefined { + return this.context.account; + } + + public set account(account: string | undefined) { + this.context.account = account; + } + + public get tableName(): string | undefined { + return this.context.tableName; + } + + public set tableName(tableName: string | undefined) { + this.context.tableName = tableName; + } + + public get xMsRequestID(): string | undefined { + return this.contextID; + } + + public set xMsRequestID(xMsRequestID: string | undefined) { + this.contextID = xMsRequestID; + } + + public get accept(): string | undefined { + return this.context.accept; + } + + public set accept(accept: string | undefined) { + this.context.accept = accept; + } +} diff --git a/src/table/errors/NotImplementedError.ts b/src/table/errors/NotImplementedError.ts new file mode 100644 index 000000000..84940ac79 --- /dev/null +++ b/src/table/errors/NotImplementedError.ts @@ -0,0 +1,19 @@ +import StorageError from "./StorageError"; + +/** + * Create customized error types by inheriting ServerError + * + * @export + * @class UnimplementedError + * @extends {StorageError} + */ +export default class NotImplementedError extends StorageError { + public constructor(requestID: string = "") { + super( + 501, + "APINotImplemented", + "Current API is not implemented yet. Please vote your wanted features to https://github.com/azure/azurite/issues", + requestID + ); + } +} diff --git a/src/table/errors/StorageError.ts b/src/table/errors/StorageError.ts new file mode 100644 index 000000000..153c11dc2 --- /dev/null +++ b/src/table/errors/StorageError.ts @@ -0,0 +1,67 @@ +import { TABLE_API_VERSION } from "../../table/utils/constants"; +import MiddlewareError from "../generated/errors/MiddlewareError"; +import { jsonToXML } from "../generated/utils/xml"; + +/** + * Represents an Azure Storage Server Error. + * + * @export + * @class StorageError + * @extends {MiddlewareError} + */ +export default class StorageError extends MiddlewareError { + public readonly storageErrorCode: string; + public readonly storageErrorMessage: string; + public readonly storageRequestID: string; + + /** + * Creates an instance of StorageError. + * + * @param {number} statusCode HTTP response status code + * @param {string} storageErrorCode Azure Storage error code, will be in response body and header + * @param {string} storageErrorMessage Azure Storage error message + * @param {string} storageRequestID Azure Storage server request ID + * @param {{ [key: string]: string }} [storageAdditionalErrorMessages={}] + * Additional error messages will be included in XML body + * @memberof StorageError + */ + constructor( + statusCode: number, + storageErrorCode: string, + storageErrorMessage: string, + storageRequestID: string, + storageAdditionalErrorMessages: { [key: string]: string } = {} + ) { + const bodyInJSON: any = { + Code: storageErrorCode, + Message: `${storageErrorMessage}\nRequestId:${storageRequestID}\nTime:${new Date().toISOString()}` + }; + + for (const key in storageAdditionalErrorMessages) { + if (storageAdditionalErrorMessages.hasOwnProperty(key)) { + const element = storageAdditionalErrorMessages[key]; + bodyInJSON[key] = element; + } + } + + const bodyInXML = jsonToXML({ Error: bodyInJSON }); + + super( + statusCode, + storageErrorMessage, + storageErrorMessage, + { + "x-ms-error-code": storageErrorCode, + "x-ms-request-id": storageRequestID, + "x-ms-version": TABLE_API_VERSION + }, + bodyInXML, + "application/xml" + ); + + this.name = "StorageError"; + this.storageErrorCode = storageErrorCode; + this.storageErrorMessage = storageErrorMessage; + this.storageRequestID = storageRequestID; + } +} diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts new file mode 100644 index 000000000..dad968830 --- /dev/null +++ b/src/table/errors/StorageErrorFactory.ts @@ -0,0 +1,45 @@ +/** + * A factory class maintains all Azure Storage table service errors. + * + * @export + * @class StorageErrorFactory + */ + +import StorageError from "./StorageError"; + +const defaultID: string = "DefaultID"; + +export default class StorageErrorFactory { + public static getTableAlreadyExists( + contextID: string = defaultID + ): StorageError { + return new StorageError( + 409, + "TableAlreadyExists", + "The specified table already exists.", + contextID + ); + } + + public static getTableNameEmpty( + contextID: string = defaultID + ): StorageError { + return new StorageError( + 400, + "TableNameEmpty", + "The specified table name is empty.", + contextID + ); + } + + public static getAccountNameEmpty( + contextID: string = defaultID + ): StorageError { + return new StorageError( + 400, + "AccountNameEmpty", + "The specified account name is empty.", + contextID + ); + } +} diff --git a/src/table/generated/Context.ts b/src/table/generated/Context.ts new file mode 100644 index 000000000..e8e410867 --- /dev/null +++ b/src/table/generated/Context.ts @@ -0,0 +1,144 @@ +import Operation from "./artifacts/operation"; +import IRequest from "./IRequest"; +import IResponse from "./IResponse"; + +export interface IHandlerParameters { + [key: string]: any; +} + +/** + * Context holds generated server context information. + * Every incoming HTTP request will initialize a new context. + * + * @export + * @class Context + */ +export default class Context { + public readonly context: any; + public readonly path: string; + + /** + * Creates an instance of Context. + * Context holds generated server context information. + * Every incoming HTTP request will initialize a new context. + * + * @param {Context} context An existing Context + * @memberof Context + */ + public constructor(context: Context); + + /** + * Creates an instance of Context. + * Context holds generated server context information. + * Every incoming HTTP request will initialize a new context. + * + * @param {Object} holder Holder is an Object which used to keep context information + * @param {string} [path="context"] holder[path] is used as context object by default + * @param {IRequest} [req] + * @param {IResponse} [res] + * @memberof Context + */ + public constructor( + holder: object, + path: string, + req?: IRequest, + res?: IResponse + ); + + public constructor( + holderOrContext: object | Context, + path: string = "context", + req?: IRequest, + res?: IResponse + ) { + if (holderOrContext instanceof Context) { + this.context = holderOrContext.context; + this.path = holderOrContext.path; + } else { + const context = holderOrContext as any; + this.path = path; + + if (context[this.path] === undefined) { + context[this.path] = {}; + } + + if (typeof context[this.path] !== "object") { + throw new TypeError( + `Initialize Context error because holder.${ + this.path + } is not an object.` + ); + } + + this.context = context[this.path]; + this.request = req; + this.response = res; + } + } + + public get operation(): Operation | undefined { + return this.context.operation; + } + + public set operation(operation: Operation | undefined) { + this.context.operation = operation; + } + + public set request(request: IRequest | undefined) { + this.context.request = request; + } + + public get request(): IRequest | undefined { + return this.context.request; + } + + public get dispatchPattern(): string | undefined { + return this.context.dispatchPattern; + } + + public set dispatchPattern(path: string | undefined) { + this.context.dispatchPattern = path; + } + + public set response(response: IResponse | undefined) { + this.context.response = response; + } + + public get response(): IResponse | undefined { + return this.context.response; + } + + public get handlerParameters(): IHandlerParameters | undefined { + return this.context.handlerParameters; + } + + public set handlerParameters( + handlerParameters: IHandlerParameters | undefined + ) { + this.context.handlerParameters = handlerParameters; + } + + public get handlerResponses(): any { + return this.context.handlerResponses; + } + + public set handlerResponses(handlerResponses: any) { + this.context.handlerResponses = handlerResponses; + } + + public get contextID(): string | undefined { + return this.context.contextID; + } + + public set contextID(contextID: string | undefined) { + this.context.contextID = contextID; + } + + public set startTime(startTime: Date | undefined) { + this.context.startTime = startTime; + } + + public get startTime(): Date | undefined { + return this.context.startTime; + } +} diff --git a/src/table/generated/ExpressMiddlewareFactory.ts b/src/table/generated/ExpressMiddlewareFactory.ts new file mode 100644 index 000000000..f74ea69ee --- /dev/null +++ b/src/table/generated/ExpressMiddlewareFactory.ts @@ -0,0 +1,161 @@ +import { ErrorRequestHandler, NextFunction, Request, RequestHandler, Response } from "express"; + +import Context from "./Context"; +import ExpressRequestAdapter from "./ExpressRequestAdapter"; +import ExpressResponseAdapter from "./ExpressResponseAdapter"; +import IHandlers from "./handlers/IHandlers"; +import deserializerMiddleware from "./middleware/deserializer.middleware"; +import dispatchMiddleware from "./middleware/dispatch.middleware"; +import endMiddleware from "./middleware/end.middleware"; +import errorMiddleware from "./middleware/error.middleware"; +import HandlerMiddlewareFactory from "./middleware/HandlerMiddlewareFactory"; +import serializerMiddleware from "./middleware/serializer.middleware"; +import MiddlewareFactory from "./MiddlewareFactory"; +import ILogger from "./utils/ILogger"; + +/** + * ExpressMiddlewareFactory will generate Express compatible middleware according to swagger definitions. + * Generated middleware MUST be used by strict order: + * * dispatchMiddleware + * * DeserializerMiddleware + * * HandlerMiddleware + * * SerializerMiddleware + * * ErrorMiddleware + * * EndMiddleware + * + * @export + * @class MiddlewareFactory + */ +export default class ExpressMiddlewareFactory extends MiddlewareFactory { + /** + * Creates an instance of MiddlewareFactory. + * + * @param {ILogger} logger A valid logger + * @param {string} [contextPath="default_context"] Optional. res.locals[contextPath] will be used to hold context + * @memberof MiddlewareFactory + */ + public constructor( + logger: ILogger, + private readonly contextPath: string = "default_context" + ) { + super(logger); + } + + /** + * DispatchMiddleware is the 1s middleware should be used among other generated middleware. + * + * @returns {RequestHandler} + * @memberof MiddlewareFactory + */ + public createDispatchMiddleware(): RequestHandler { + return (req: Request, res: Response, next: NextFunction) => { + const request = new ExpressRequestAdapter(req); + const response = new ExpressResponseAdapter(res); + dispatchMiddleware( + new Context(res.locals, this.contextPath, request, response), + request, + next, + this.logger + ); + }; + } + + /** + * DeserializerMiddleware is the 2nd middleware should be used among other generated middleware. + * + * @returns {RequestHandler} + * @memberof MiddlewareFactory + */ + public createDeserializerMiddleware(): RequestHandler { + return (req: Request, res: Response, next: NextFunction) => { + const request = new ExpressRequestAdapter(req); + const response = new ExpressResponseAdapter(res); + deserializerMiddleware( + new Context(res.locals, this.contextPath, request, response), + request, + next, + this.logger + ); + }; + } + + /** + * HandlerMiddleware is the 3rd middleware should be used among other generated middleware. + * + * @param {IHandlers} handlers + * @returns {RequestHandler} + * @memberof MiddlewareFactory + */ + public createHandlerMiddleware(handlers: IHandlers): RequestHandler { + const handlerMiddlewareFactory = new HandlerMiddlewareFactory( + handlers, + this.logger + ); + return (req: Request, res: Response, next: NextFunction) => { + const request = new ExpressRequestAdapter(req); + const response = new ExpressResponseAdapter(res); + handlerMiddlewareFactory.createHandlerMiddleware()( + new Context(res.locals, this.contextPath, request, response), + next + ); + }; + } + + /** + * SerializerMiddleware is the 4st middleware should be used among other generated middleware. + * + * @returns {RequestHandler} + * @memberof MiddlewareFactory + */ + public createSerializerMiddleware(): RequestHandler { + return (req: Request, res: Response, next: NextFunction) => { + const request = new ExpressRequestAdapter(req); + const response = new ExpressResponseAdapter(res); + serializerMiddleware( + new Context(res.locals, this.contextPath, request, response), + new ExpressResponseAdapter(res), + next, + this.logger + ); + }; + } + + /** + * ErrorMiddleware is the 5st middleware should be used among other generated middleware. + * + * @returns {ErrorRequestHandler} + * @memberof MiddlewareFactory + */ + public createErrorMiddleware(): ErrorRequestHandler { + return (err: Error, req: Request, res: Response, next: NextFunction) => { + const request = new ExpressRequestAdapter(req); + const response = new ExpressResponseAdapter(res); + errorMiddleware( + new Context(res.locals, this.contextPath, request, response), + err, + new ExpressRequestAdapter(req), + new ExpressResponseAdapter(res), + next, + this.logger + ); + }; + } + + /** + * EndMiddleware is the 6st middleware should be used among other generated middleware. + * + * @returns {RequestHandler} + * @memberof MiddlewareFactory + */ + public createEndMiddleware(): RequestHandler { + return (req: Request, res: Response) => { + const request = new ExpressRequestAdapter(req); + const response = new ExpressResponseAdapter(res); + endMiddleware( + new Context(res.locals, this.contextPath, request, response), + new ExpressResponseAdapter(res), + this.logger + ); + }; + } +} diff --git a/src/table/generated/ExpressRequestAdapter.ts b/src/table/generated/ExpressRequestAdapter.ts new file mode 100644 index 000000000..c37abcb31 --- /dev/null +++ b/src/table/generated/ExpressRequestAdapter.ts @@ -0,0 +1,57 @@ +import { Request } from "express"; + +import IRequest, { HttpMethod } from "./IRequest"; + +export default class ExpressRequestAdapter implements IRequest { + public constructor(private readonly req: Request) {} + + public getMethod(): HttpMethod { + return this.req.method.toUpperCase() as HttpMethod; + } + + public getUrl(): string { + return this.req.url; + } + + public getEndpoint(): string { + return `${this.req.protocol}://${this.getHeader("host") || + this.req.hostname}`; + } + + public getPath(): string { + return this.req.path; + } + + public getBodyStream(): NodeJS.ReadableStream { + return this.req; + } + + public getBody(): string | undefined { + return this.req.body; + } + + public setBody(body: string | undefined): ExpressRequestAdapter { + this.req.body = body; + return this; + } + + public getHeader(field: string): string | undefined { + return this.req.header(field); + } + + public getHeaders(): { [header: string]: string | string[] | undefined } { + return this.req.headers; + } + + public getRawHeaders(): string[] { + return this.req.rawHeaders; + } + + public getQuery(key: string): string | undefined { + return this.req.query[key]; + } + + public getProtocol(): string { + return this.req.protocol; + } +} diff --git a/src/table/generated/ExpressResponseAdapter.ts b/src/table/generated/ExpressResponseAdapter.ts new file mode 100644 index 000000000..d938a41ea --- /dev/null +++ b/src/table/generated/ExpressResponseAdapter.ts @@ -0,0 +1,62 @@ +import { Response } from "express"; +import { OutgoingHttpHeaders } from "http"; + +import IResponse from "./IResponse"; + +export default class ExpressResponseAdapter implements IResponse { + public constructor(private readonly res: Response) {} + + public setStatusCode(code: number): IResponse { + this.res.status(code); + return this; + } + + public getStatusCode(): number { + return this.res.statusCode; + } + + public setStatusMessage(message: string): IResponse { + this.res.statusMessage = message; + return this; + } + + public getStatusMessage(): string { + return this.res.statusMessage; + } + + public setHeader( + field: string, + value?: string | string[] | undefined | number | boolean + ): IResponse { + if (typeof value === "number") { + value = `${value}`; + } + + if (typeof value === "boolean") { + value = `${value}`; + } + + // Cannot remove if block because of a potential TypeScript bug + if (typeof value === "string" || value instanceof Array) { + this.res.setHeader(field, value); + } + return this; + } + + public getHeaders(): OutgoingHttpHeaders { + return this.res.getHeaders(); + } + + public headersSent(): boolean { + return this.res.headersSent; + } + + public setContentType(value: string): IResponse { + this.res.setHeader("content-type", value); + return this; + } + + public getBodyStream(): NodeJS.WritableStream { + return this.res; + } +} diff --git a/src/table/generated/IRequest.ts b/src/table/generated/IRequest.ts new file mode 100644 index 000000000..df39dd0ad --- /dev/null +++ b/src/table/generated/IRequest.ts @@ -0,0 +1,25 @@ +export type HttpMethod = + | "GET" + | "HEAD" + | "POST" + | "PUT" + | "DELETE" + | "CONNECT" + | "OPTIONS" + | "TRACE" + | "PATCH"; + +export default interface IRequest { + getMethod(): HttpMethod; + getUrl(): string; + getEndpoint(): string; + getPath(): string; + getBodyStream(): NodeJS.ReadableStream; + setBody(body: string | undefined): IRequest; + getBody(): string | undefined; + getHeader(field: string): string | undefined; + getHeaders(): { [header: string]: string | string[] | undefined }; + getRawHeaders(): string[]; + getQuery(key: string): string | undefined; + getProtocol(): string; +} diff --git a/src/table/generated/IResponse.ts b/src/table/generated/IResponse.ts new file mode 100644 index 000000000..d611d9618 --- /dev/null +++ b/src/table/generated/IResponse.ts @@ -0,0 +1,16 @@ +import { OutgoingHttpHeaders } from "http"; + +export default interface IResponse { + setStatusCode(code: number): IResponse; + getStatusCode(): number; + setStatusMessage(message: string): IResponse; + getStatusMessage(): string; + setHeader( + field: string, + value?: string | string[] | undefined | number | boolean + ): IResponse; + getHeaders(): OutgoingHttpHeaders; + headersSent(): boolean; + setContentType(value: string | undefined): IResponse; + getBodyStream(): NodeJS.WritableStream; +} diff --git a/src/table/generated/MiddlewareFactory.ts b/src/table/generated/MiddlewareFactory.ts new file mode 100644 index 000000000..8883be2e7 --- /dev/null +++ b/src/table/generated/MiddlewareFactory.ts @@ -0,0 +1,91 @@ +import IHandlers from "./handlers/IHandlers"; +import ILogger from "./utils/ILogger"; + +export type Callback = (...args: any[]) => any; +export type MiddlewareTypes = Callback; +export type NextFunction = Callback; + +/** + * MiddlewareFactory will generate middleware according to swagger definitions. + * + * Generated middleware MUST be used by strict order when you build your HTTP server: + * * DispatchMiddleware + * * DeserializerMiddleware + * * HandlerMiddleware + * * SerializerMiddleware + * * ErrorMiddleware + * * EndMiddleware + * + * To compatible with different Node.js server frameworks, such as Express or Koa, + * Extend this class and implement interfaces IRequest and IResponse as adapters. + * + * As above default generated middleware is callback style, you may want to wrap them into promise + * style for Koa like frameworks. Generated middleware will always trigger callback method at last, + * and pass all error object as the first parameter of callback method. + * + * We already provide implementation for Express framework. Refer to: + * * ExpressMiddlewareFactory + * * ExpressRequestAdapter + * * ExpressResponseAdapter + * + * @export + * @class MiddlewareFactory + */ +export default abstract class MiddlewareFactory { + /** + * Creates an instance of MiddlewareFactory. + * + * @param {ILogger} logger A valid logger + * @memberof MiddlewareFactory + */ + public constructor(protected readonly logger: ILogger) {} + + /** + * DispatchMiddleware is the 1s middleware should be used among other generated middleware. + * + * @returns {MiddlewareTypes} + * @memberof MiddlewareFactory + */ + public abstract createDispatchMiddleware(): MiddlewareTypes; + + /** + * DeserializerMiddleware is the 2nd middleware should be used among other generated middleware. + * + * @returns {MiddlewareTypes} + * @memberof MiddlewareFactory + */ + public abstract createDeserializerMiddleware(): MiddlewareTypes; + + /** + * HandlerMiddleware is the 3rd middleware should be used among other generated middleware. + * + * @param {IHandlers} handlers + * @returns {MiddlewareTypes} + * @memberof MiddlewareFactory + */ + public abstract createHandlerMiddleware(handlers: IHandlers): MiddlewareTypes; + + /** + * SerializerMiddleware is the 4st middleware should be used among other generated middleware. + * + * @returns {MiddlewareTypes} + * @memberof MiddlewareFactory + */ + public abstract createSerializerMiddleware(): MiddlewareTypes; + + /** + * ErrorMiddleware is the 5st middleware should be used among other generated middleware. + * + * @returns {MiddlewareTypes} + * @memberof MiddlewareFactory + */ + public abstract createErrorMiddleware(): MiddlewareTypes; + + /** + * EndMiddleware is the 6st middleware should be used among other generated middleware. + * + * @returns {MiddlewareTypes} + * @memberof MiddlewareFactory + */ + public abstract createEndMiddleware(): MiddlewareTypes; +} diff --git a/src/table/generated/artifacts/mappers.ts b/src/table/generated/artifacts/mappers.ts new file mode 100644 index 000000000..40f3992c6 --- /dev/null +++ b/src/table/generated/artifacts/mappers.ts @@ -0,0 +1,1168 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ +// tslint:disable:object-literal-sort-keys + +import * as msRest from "@azure/ms-rest-js"; + +export const TableServiceError: msRest.CompositeMapper = { + serializedName: "TableServiceError", + type: { + name: "Composite", + className: "TableServiceError", + modelProperties: { + message: { + xmlName: "Message", + serializedName: "Message", + type: { + name: "String" + } + } + } + } +}; + +export const RetentionPolicy: msRest.CompositeMapper = { + serializedName: "RetentionPolicy", + type: { + name: "Composite", + className: "RetentionPolicy", + modelProperties: { + enabled: { + xmlName: "Enabled", + required: true, + serializedName: "Enabled", + type: { + name: "Boolean" + } + }, + days: { + xmlName: "Days", + serializedName: "Days", + constraints: { + InclusiveMinimum: 1 + }, + type: { + name: "Number" + } + } + } + } +}; + +export const Logging: msRest.CompositeMapper = { + serializedName: "Logging", + type: { + name: "Composite", + className: "Logging", + modelProperties: { + version: { + xmlName: "Version", + required: true, + serializedName: "Version", + type: { + name: "String" + } + }, + deleteProperty: { + xmlName: "Delete", + required: true, + serializedName: "Delete", + type: { + name: "Boolean" + } + }, + read: { + xmlName: "Read", + required: true, + serializedName: "Read", + type: { + name: "Boolean" + } + }, + write: { + xmlName: "Write", + required: true, + serializedName: "Write", + type: { + name: "Boolean" + } + }, + retentionPolicy: { + xmlName: "RetentionPolicy", + required: true, + serializedName: "RetentionPolicy", + type: { + name: "Composite", + className: "RetentionPolicy" + } + } + } + } +}; + +export const Metrics: msRest.CompositeMapper = { + serializedName: "Metrics", + type: { + name: "Composite", + className: "Metrics", + modelProperties: { + version: { + xmlName: "Version", + serializedName: "Version", + type: { + name: "String" + } + }, + enabled: { + xmlName: "Enabled", + required: true, + serializedName: "Enabled", + type: { + name: "Boolean" + } + }, + includeAPIs: { + xmlName: "IncludeAPIs", + serializedName: "IncludeAPIs", + type: { + name: "Boolean" + } + }, + retentionPolicy: { + xmlName: "RetentionPolicy", + serializedName: "RetentionPolicy", + type: { + name: "Composite", + className: "RetentionPolicy" + } + } + } + } +}; + +export const CorsRule: msRest.CompositeMapper = { + serializedName: "CorsRule", + type: { + name: "Composite", + className: "CorsRule", + modelProperties: { + allowedOrigins: { + xmlName: "AllowedOrigins", + required: true, + serializedName: "AllowedOrigins", + type: { + name: "String" + } + }, + allowedMethods: { + xmlName: "AllowedMethods", + required: true, + serializedName: "AllowedMethods", + type: { + name: "String" + } + }, + allowedHeaders: { + xmlName: "AllowedHeaders", + required: true, + serializedName: "AllowedHeaders", + type: { + name: "String" + } + }, + exposedHeaders: { + xmlName: "ExposedHeaders", + required: true, + serializedName: "ExposedHeaders", + type: { + name: "String" + } + }, + maxAgeInSeconds: { + xmlName: "MaxAgeInSeconds", + required: true, + serializedName: "MaxAgeInSeconds", + constraints: { + InclusiveMinimum: 0 + }, + type: { + name: "Number" + } + } + } + } +}; + +export const TableServiceProperties: msRest.CompositeMapper = { + xmlName: "StorageServiceProperties", + serializedName: "TableServiceProperties", + type: { + name: "Composite", + className: "TableServiceProperties", + modelProperties: { + logging: { + xmlName: "Logging", + serializedName: "Logging", + type: { + name: "Composite", + className: "Logging" + } + }, + hourMetrics: { + xmlName: "HourMetrics", + serializedName: "HourMetrics", + type: { + name: "Composite", + className: "Metrics" + } + }, + minuteMetrics: { + xmlName: "MinuteMetrics", + serializedName: "MinuteMetrics", + type: { + name: "Composite", + className: "Metrics" + } + }, + cors: { + xmlIsWrapped: true, + xmlName: "Cors", + xmlElementName: "CorsRule", + serializedName: "Cors", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "CorsRule" + } + } + } + } + } + } +}; + +export const GeoReplication: msRest.CompositeMapper = { + serializedName: "GeoReplication", + type: { + name: "Composite", + className: "GeoReplication", + modelProperties: { + status: { + xmlName: "Status", + required: true, + serializedName: "Status", + type: { + name: "String" + } + }, + lastSyncTime: { + xmlName: "LastSyncTime", + required: true, + serializedName: "LastSyncTime", + type: { + name: "DateTimeRfc1123" + } + } + } + } +}; + +export const TableServiceStats: msRest.CompositeMapper = { + xmlName: "StorageServiceStats", + serializedName: "TableServiceStats", + type: { + name: "Composite", + className: "TableServiceStats", + modelProperties: { + geoReplication: { + xmlName: "GeoReplication", + serializedName: "GeoReplication", + type: { + name: "Composite", + className: "GeoReplication" + } + } + } + } +}; + +export const TableProperties: msRest.CompositeMapper = { + serializedName: "TableProperties", + type: { + name: "Composite", + className: "TableProperties", + modelProperties: { + tableName: { + xmlName: "TableName", + serializedName: "TableName", + type: { + name: "String" + } + } + } + } +}; + +export const TableResponse: msRest.CompositeMapper = { + serializedName: "TableResponse", + type: { + name: "Composite", + className: "TableResponse", + modelProperties: { + odatametadata: { + xmlName: "odata.metadata", + serializedName: "odata\\.metadata", + type: { + name: "String" + } + }, + tableName: { + xmlName: "TableName", + serializedName: "TableName", + type: { + name: "String" + } + }, + odatatype: { + xmlName: "odata.type", + serializedName: "odata\\.type", + type: { + name: "String" + } + }, + odataid: { + xmlName: "odata.id", + serializedName: "odata\\.id", + type: { + name: "String" + } + }, + odataeditLink: { + xmlName: "odata.editLink", + serializedName: "odata\\.editLink", + type: { + name: "String" + } + } + } + } +}; + +export const TableResponseProperties: msRest.CompositeMapper = { + serializedName: "TableResponseProperties", + type: { + name: "Composite", + className: "TableResponseProperties", + modelProperties: { + tableName: { + xmlName: "TableName", + serializedName: "TableName", + type: { + name: "String" + } + }, + odatatype: { + xmlName: "odata.type", + serializedName: "odata\\.type", + type: { + name: "String" + } + }, + odataid: { + xmlName: "odata.id", + serializedName: "odata\\.id", + type: { + name: "String" + } + }, + odataeditLink: { + xmlName: "odata.editLink", + serializedName: "odata\\.editLink", + type: { + name: "String" + } + } + } + } +}; + +export const TableQueryResponse: msRest.CompositeMapper = { + serializedName: "TableQueryResponse", + type: { + name: "Composite", + className: "TableQueryResponse", + modelProperties: { + odatametadata: { + xmlName: "odata.metadata", + serializedName: "odata\\.metadata", + type: { + name: "String" + } + }, + value: { + xmlName: "value", + xmlElementName: "TableResponseProperties", + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "TableResponseProperties" + } + } + } + } + } + } +}; + +export const AccessPolicy: msRest.CompositeMapper = { + serializedName: "AccessPolicy", + type: { + name: "Composite", + className: "AccessPolicy", + modelProperties: { + start: { + xmlName: "Start", + required: true, + serializedName: "Start", + type: { + name: "String" + } + }, + expiry: { + xmlName: "Expiry", + required: true, + serializedName: "Expiry", + type: { + name: "String" + } + }, + permission: { + xmlName: "Permission", + required: true, + serializedName: "Permission", + type: { + name: "String" + } + } + } + } +}; + +export const SignedIdentifier: msRest.CompositeMapper = { + serializedName: "SignedIdentifier", + type: { + name: "Composite", + className: "SignedIdentifier", + modelProperties: { + id: { + xmlName: "Id", + required: true, + serializedName: "Id", + type: { + name: "String" + } + }, + accessPolicy: { + xmlName: "AccessPolicy", + required: true, + serializedName: "AccessPolicy", + type: { + name: "Composite", + className: "AccessPolicy" + } + } + } + } +}; + +export const TableEntityQueryResponse: msRest.CompositeMapper = { + serializedName: "TableEntityQueryResponse", + type: { + name: "Composite", + className: "TableEntityQueryResponse", + modelProperties: { + odatametadata: { + xmlName: "odata.metadata", + serializedName: "odata\\.metadata", + type: { + name: "String" + } + }, + value: { + xmlName: "value", + serializedName: "value", + type: { + name: "Sequence", + element: { + type: { + name: "Dictionary", + value: { + type: { + name: "Object" + } + } + } + } + } + } + } + } +}; + +export const QueryOptions: msRest.CompositeMapper = { + xmlName: "QueryOptions", + type: { + name: "Composite", + className: "QueryOptions", + modelProperties: { + format: { + xmlName: "format", + type: { + name: "String" + } + }, + top: { + xmlName: "top", + type: { + name: "Number" + } + }, + select: { + xmlName: "select", + type: { + name: "String" + } + }, + filter: { + xmlName: "filter", + type: { + name: "String" + } + } + } + } +}; + +export const TableQueryHeaders: msRest.CompositeMapper = { + serializedName: "table-query-headers", + type: { + name: "Composite", + className: "TableQueryHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + xMsContinuationNextTableName: { + serializedName: "x-ms-continuation-nexttablename", + type: { + name: "String" + } + } + } + } +}; + +export const TableCreateHeaders: msRest.CompositeMapper = { + serializedName: "table-create-headers", + type: { + name: "Composite", + className: "TableCreateHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + preferenceApplied: { + serializedName: "preference-applied", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableDeleteHeaders: msRest.CompositeMapper = { + serializedName: "table-delete-headers", + type: { + name: "Composite", + className: "TableDeleteHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableQueryEntitiesHeaders: msRest.CompositeMapper = { + serializedName: "table-queryentities-headers", + type: { + name: "Composite", + className: "TableQueryEntitiesHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + xMsContinuationNextPartitionKey: { + serializedName: "x-ms-continuation-nextpartitionkey", + type: { + name: "String" + } + }, + xMsContinuationNextRowKey: { + serializedName: "x-ms-continuation-nextrowkey", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableQueryEntitiesWithPartitionAndRowKeyHeaders: msRest.CompositeMapper = { + serializedName: "table-queryentitieswithpartitionandrowkey-headers", + type: { + name: "Composite", + className: "TableQueryEntitiesWithPartitionAndRowKeyHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + eTag: { + serializedName: "etag", + type: { + name: "String" + } + }, + xMsContinuationNextPartitionKey: { + serializedName: "x-ms-continuation-nextpartitionkey", + type: { + name: "String" + } + }, + xMsContinuationNextRowKey: { + serializedName: "x-ms-continuation-nextrowkey", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableUpdateEntityHeaders: msRest.CompositeMapper = { + serializedName: "table-updateentity-headers", + type: { + name: "Composite", + className: "TableUpdateEntityHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + eTag: { + serializedName: "etag", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableMergeEntityHeaders: msRest.CompositeMapper = { + serializedName: "table-mergeentity-headers", + type: { + name: "Composite", + className: "TableMergeEntityHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + eTag: { + serializedName: "etag", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableDeleteEntityHeaders: msRest.CompositeMapper = { + serializedName: "table-deleteentity-headers", + type: { + name: "Composite", + className: "TableDeleteEntityHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableInsertEntityHeaders: msRest.CompositeMapper = { + serializedName: "table-insertentity-headers", + type: { + name: "Composite", + className: "TableInsertEntityHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + eTag: { + serializedName: "etag", + type: { + name: "String" + } + }, + preferenceApplied: { + serializedName: "preference-applied", + type: { + name: "String" + } + }, + contentType: { + serializedName: "content-type", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableGetAccessPolicyHeaders: msRest.CompositeMapper = { + serializedName: "table-getaccesspolicy-headers", + type: { + name: "Composite", + className: "TableGetAccessPolicyHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const TableSetAccessPolicyHeaders: msRest.CompositeMapper = { + serializedName: "table-setaccesspolicy-headers", + type: { + name: "Composite", + className: "TableSetAccessPolicyHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const ServiceSetPropertiesHeaders: msRest.CompositeMapper = { + serializedName: "service-setproperties-headers", + type: { + name: "Composite", + className: "ServiceSetPropertiesHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const ServiceGetPropertiesHeaders: msRest.CompositeMapper = { + serializedName: "service-getproperties-headers", + type: { + name: "Composite", + className: "ServiceGetPropertiesHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + +export const ServiceGetStatisticsHeaders: msRest.CompositeMapper = { + serializedName: "service-getstatistics-headers", + type: { + name: "Composite", + className: "ServiceGetStatisticsHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; diff --git a/src/table/generated/artifacts/models.ts b/src/table/generated/artifacts/models.ts new file mode 100644 index 000000000..72ed20ca2 --- /dev/null +++ b/src/table/generated/artifacts/models.ts @@ -0,0 +1,1470 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +// tslint:disable:max-line-length +// tslint:disable:interface-name +// tslint:disable:quotemark + +/** + * Table Service error. + */ +export interface TableServiceError { + /** + * The error message. + */ + message?: string; +} + +/** + * The retention policy. + */ +export interface RetentionPolicy { + /** + * Indicates whether a retention policy is enabled for the service. + */ + enabled: boolean; + /** + * Indicates the number of days that metrics or logging or soft-deleted data should be retained. + * All data older than this value will be deleted. + */ + days?: number; +} + +/** + * Azure Analytics Logging settings. + */ +export interface Logging { + /** + * The version of Analytics to configure. + */ + version: string; + /** + * Indicates whether all delete requests should be logged. + */ + deleteProperty: boolean; + /** + * Indicates whether all read requests should be logged. + */ + read: boolean; + /** + * Indicates whether all write requests should be logged. + */ + write: boolean; + retentionPolicy: RetentionPolicy; +} + +/** + * An interface representing Metrics. + */ +export interface Metrics { + /** + * The version of Analytics to configure. + */ + version?: string; + /** + * Indicates whether metrics are enabled for the Table service. + */ + enabled: boolean; + /** + * Indicates whether metrics should generate summary statistics for called API operations. + */ + includeAPIs?: boolean; + retentionPolicy?: RetentionPolicy; +} + +/** + * CORS is an HTTP feature that enables a web application running under one domain to access + * resources in another domain. Web browsers implement a security restriction known as same-origin + * policy that prevents a web page from calling APIs in a different domain; CORS provides a secure + * way to allow one domain (the origin domain) to call APIs in another domain. + */ +export interface CorsRule { + /** + * The origin domains that are permitted to make a request against the service via CORS. The + * origin domain is the domain from which the request originates. Note that the origin must be an + * exact case-sensitive match with the origin that the user age sends to the service. You can + * also use the wildcard character '*' to allow all origin domains to make requests via CORS. + */ + allowedOrigins: string; + /** + * The methods (HTTP request verbs) that the origin domain may use for a CORS request. (comma + * separated) + */ + allowedMethods: string; + /** + * The request headers that the origin domain may specify on the CORS request. + */ + allowedHeaders: string; + /** + * The response headers that may be sent in the response to the CORS request and exposed by the + * browser to the request issuer. + */ + exposedHeaders: string; + /** + * The maximum amount time that a browser should cache the preflight OPTIONS request. + */ + maxAgeInSeconds: number; +} + +/** + * Table Service Properties. + */ +export interface TableServiceProperties { + /** + * Azure Analytics Logging settings. + */ + logging?: Logging; + /** + * A summary of request statistics grouped by API in hourly aggregates for tables. + */ + hourMetrics?: Metrics; + /** + * A summary of request statistics grouped by API in minute aggregates for tables. + */ + minuteMetrics?: Metrics; + /** + * The set of CORS rules. + */ + cors?: CorsRule[]; +} + +/** + * An interface representing GeoReplication. + */ +export interface GeoReplication { + /** + * The status of the secondary location. Possible values include: 'live', 'bootstrap', + * 'unavailable' + */ + status: GeoReplicationStatusType; + /** + * A GMT date/time value, to the second. All primary writes preceding this value are guaranteed + * to be available for read operations at the secondary. Primary writes after this point in time + * may or may not be available for reads. + */ + lastSyncTime: Date; +} + +/** + * Stats for the service. + */ +export interface TableServiceStats { + /** + * Geo-Replication information for the Secondary Storage Service. + */ + geoReplication?: GeoReplication; +} + +/** + * The properties for creating a table. + */ +export interface TableProperties { + /** + * The name of the table to create. + */ + tableName?: string; +} + +/** + * The response for a single table. + */ +export interface TableResponse { + /** + * The metadata response of the table. + */ + odatametadata?: string; + /** + * The name of the table. + */ + tableName?: string; + /** + * The odata type of the table. + */ + odatatype?: string; + /** + * The id of the table. + */ + odataid?: string; + /** + * The edit link of the table. + */ + odataeditLink?: string; +} + +/** + * The properties for the table response. + */ +export interface TableResponseProperties { + /** + * The name of the table. + */ + tableName?: string; + /** + * The odata type of the table. + */ + odatatype?: string; + /** + * The id of the table. + */ + odataid?: string; + /** + * The edit link of the table. + */ + odataeditLink?: string; +} + +/** + * The properties for the table query response. + */ +export interface TableQueryResponse { + /** + * The metadata response of the table. + */ + odatametadata?: string; + /** + * List of tables. + */ + value?: TableResponseProperties[]; +} + +/** + * An Access policy. + */ +export interface AccessPolicy { + /** + * The start datetime from which the policy is active. + * **NOTE: This entity will be treated as a string instead of a Date because the API can + * potentially deal with a higher precision value than what is supported by JavaScript.** + */ + start: string; + /** + * The datetime that the policy expires. + * **NOTE: This entity will be treated as a string instead of a Date because the API can + * potentially deal with a higher precision value than what is supported by JavaScript.** + */ + expiry: string; + /** + * The permissions for the acl policy. + */ + permission: string; +} + +/** + * A signed identifier. + */ +export interface SignedIdentifier { + /** + * A unique id. + */ + id: string; + /** + * The access policy. + */ + accessPolicy: AccessPolicy; +} + +/** + * The properties for the table entity query response. + */ +export interface TableEntityQueryResponse { + /** + * The metadata response of the table. + */ + odatametadata?: string; + /** + * List of table entities. + */ + value?: { [propertyName: string]: any }[]; +} + +/** + * Additional parameters for a set of operations. + */ +export interface QueryOptions { + /** + * Specifies the media type for the response. Possible values include: + * 'application/json;odata=nometadata', 'application/json;odata=minimalmetadata', + * 'application/json;odata=fullmetadata' + */ + format?: OdataMetadataFormat; + /** + * Maximum number of records to return. + */ + top?: number; + /** + * Select expression using OData notation. Limits the columns on each record to just those + * requested, e.g. "$select=PolicyAssignmentId, ResourceId". + */ + select?: string; + /** + * OData filter expression. + */ + filter?: string; +} + +/** + * An interface representing AzuriteServerTableOptions. + */ +export interface AzuriteServerTableOptions { + /** + * Specifies the version of the operation to use for this request. Possible values include: + * '2019-02-02' + */ + version?: Version; +} + +/** + * Optional Parameters. + */ +export interface TableQueryOptionalParams { + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion; + /** + * A table query continuation token from a previous call. + */ + nextTableName?: string; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableCreateOptionalParams { + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion1; + /** + * Specifies whether the response should include the inserted entity in the payload. Possible + * values are return-no-content and return-content. Possible values include: 'return-no-content', + * 'return-content' + */ + responsePreference?: ResponseFormat; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableDeleteMethodOptionalParams { + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; +} + +/** + * Optional Parameters. + */ +export interface TableQueryEntitiesOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion2; + /** + * An entity query continuation token from a previous call. + */ + nextPartitionKey?: string; + /** + * An entity query continuation token from a previous call. + */ + nextRowKey?: string; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableQueryEntitiesWithPartitionAndRowKeyOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion3; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableUpdateEntityOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion4; + /** + * The properties for the table entity. + */ + tableEntityProperties?: { [propertyName: string]: any }; + /** + * Match condition for an entity to be updated. If specified and a matching entity is not found, + * an error will be raised. To force an unconditional update, set to the wildcard character (*). + * If not specified, an insert will be performed when no existing entity is found to update and a + * replace will be performed if an existing entity is found. + */ + ifMatch?: string; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableMergeEntityOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion5; + /** + * The properties for the table entity. + */ + tableEntityProperties?: { [propertyName: string]: any }; + /** + * Match condition for an entity to be updated. If specified and a matching entity is not found, + * an error will be raised. To force an unconditional update, set to the wildcard character (*). + * If not specified, an insert will be performed when no existing entity is found to update and a + * merge will be performed if an existing entity is found. + */ + ifMatch?: string; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableDeleteEntityOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion6; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableInsertEntityOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion7; + /** + * The properties for the table entity. + */ + tableEntityProperties?: { [propertyName: string]: any }; + /** + * Specifies whether the response should include the inserted entity in the payload. Possible + * values are return-no-content and return-content. Possible values include: 'return-no-content', + * 'return-content' + */ + responsePreference?: ResponseFormat; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableGetAccessPolicyOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; +} + +/** + * Optional Parameters. + */ +export interface TableSetAccessPolicyOptionalParams { + /** + * The acls for the table. + */ + tableAcl?: SignedIdentifier[]; + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; +} + +/** + * Optional Parameters. + */ +export interface ServiceSetPropertiesOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; +} + +/** + * Optional Parameters. + */ +export interface ServiceGetPropertiesOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; +} + +/** + * Optional Parameters. + */ +export interface ServiceGetStatisticsOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; +} + +/** + * Defines headers for Query operation. + */ +export interface TableQueryHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + /** + * This header contains the continuation token value. + */ + xMsContinuationNextTableName?: string; +} + +/** + * Defines headers for Create operation. + */ +export interface TableCreateHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + /** + * Indicates whether the Prefer request header was honored. If the response does not include this + * header, then the Prefer header was not honored. If this header is returned, its value will + * either be return-content or return-no-content. + */ + preferenceApplied?: string; + errorCode?: string; +} + +/** + * Defines headers for Delete operation. + */ +export interface TableDeleteHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + errorCode?: string; +} + +/** + * Defines headers for QueryEntities operation. + */ +export interface TableQueryEntitiesHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + /** + * This header contains the continuation token value for partition key. + */ + xMsContinuationNextPartitionKey?: string; + /** + * This header contains the continuation token value for row key. + */ + xMsContinuationNextRowKey?: string; + errorCode?: string; +} + +/** + * Defines headers for QueryEntitiesWithPartitionAndRowKey operation. + */ +export interface TableQueryEntitiesWithPartitionAndRowKeyHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated + */ + eTag?: string; + /** + * This header contains the continuation token value for partition key. + */ + xMsContinuationNextPartitionKey?: string; + /** + * This header contains the continuation token value for row key. + */ + xMsContinuationNextRowKey?: string; + errorCode?: string; +} + +/** + * Defines headers for UpdateEntity operation. + */ +export interface TableUpdateEntityHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + /** + * UTC date/time value generated by the service that indicates the time at which the entity was + * last updated. + */ + eTag?: string; + errorCode?: string; +} + +/** + * Defines headers for MergeEntity operation. + */ +export interface TableMergeEntityHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + /** + * UTC date/time value generated by the service that indicates the time at which the entity was + * last updated. + */ + eTag?: string; + errorCode?: string; +} + +/** + * Defines headers for DeleteEntity operation. + */ +export interface TableDeleteEntityHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + errorCode?: string; +} + +/** + * Defines headers for InsertEntity operation. + */ +export interface TableInsertEntityHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + /** + * UTC date/time value generated by the service that indicates the time at which the entity was + * last updated. + */ + eTag?: string; + /** + * Indicates whether the Prefer request header was honored. If the response does not include this + * header, then the Prefer header was not honored. If this header is returned, its value will + * either be return-content or return-no-content. + */ + preferenceApplied?: string; + /** + * Indicates the content type of the payload. The value depends on the value specified for the + * Accept request header. + */ + contentType?: string; + errorCode?: string; +} + +/** + * Defines headers for GetAccessPolicy operation. + */ +export interface TableGetAccessPolicyHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + errorCode?: string; +} + +/** + * Defines headers for SetAccessPolicy operation. + */ +export interface TableSetAccessPolicyHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + errorCode?: string; +} + +/** + * Defines headers for SetProperties operation. + */ +export interface ServiceSetPropertiesHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + errorCode?: string; +} + +/** + * Defines headers for GetProperties operation. + */ +export interface ServiceGetPropertiesHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + errorCode?: string; +} + +/** + * Defines headers for GetStatistics operation. + */ +export interface ServiceGetStatisticsHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + errorCode?: string; +} + +/** + * Defines values for GeoReplicationStatusType. + * Possible values include: 'live', 'bootstrap', 'unavailable' + * @readonly + * @enum {string} + */ +export enum GeoReplicationStatusType { + Live = 'live', + Bootstrap = 'bootstrap', + Unavailable = 'unavailable', +} + +/** + * Defines values for OdataMetadataFormat. + * Possible values include: 'application/json;odata=nometadata', + * 'application/json;odata=minimalmetadata', 'application/json;odata=fullmetadata' + * @readonly + * @enum {string} + */ +export enum OdataMetadataFormat { + Applicationjsonodatanometadata = 'application/json;odata=nometadata', + Applicationjsonodataminimalmetadata = 'application/json;odata=minimalmetadata', + Applicationjsonodatafullmetadata = 'application/json;odata=fullmetadata', +} + +/** + * Defines values for ResponseFormat. + * Possible values include: 'return-no-content', 'return-content' + * @readonly + * @enum {string} + */ +export enum ResponseFormat { + ReturnNoContent = 'return-no-content', + ReturnContent = 'return-content', +} + +/** + * Defines values for Version. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for DataServiceVersion. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion { + ThreeFullStopZero = '3.0', +} + +/** + * Defines values for DataServiceVersion1. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion1 { + ThreeFullStopZero = '3.0', +} + +/** + * Defines values for DataServiceVersion2. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion2 { + ThreeFullStopZero = '3.0', +} + +/** + * Defines values for DataServiceVersion3. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion3 { + ThreeFullStopZero = '3.0', +} + +/** + * Defines values for DataServiceVersion4. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion4 { + ThreeFullStopZero = '3.0', +} + +/** + * Defines values for DataServiceVersion5. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion5 { + ThreeFullStopZero = '3.0', +} + +/** + * Defines values for DataServiceVersion6. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion6 { + ThreeFullStopZero = '3.0', +} + +/** + * Defines values for DataServiceVersion7. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion7 { + ThreeFullStopZero = '3.0', +} + +/** + * Defines values for Version1. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version1 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version2. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version2 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version3. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version3 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version4. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version4 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version5. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version5 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version6. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version6 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version7. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version7 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version8. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version8 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version9. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version9 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version10. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version10 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version11. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version11 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version12. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version12 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version13. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version13 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Defines values for Version14. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version14 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + +/** + * Contains response data for the query operation. + */ +export type TableQueryResponse2 = TableQueryResponse & TableQueryHeaders & { + /** + * The response status code. + */ + statusCode: 200; +}; + +/** + * Contains response data for the create operation. + */ +export type TableCreateResponse = TableResponse & TableCreateHeaders & { + /** + * The response status code. + */ + statusCode: 201 | 204; +}; + +/** + * Contains response data for the deleteMethod operation. + */ +export type TableDeleteResponse = TableDeleteHeaders & { + /** + * The response status code. + */ + statusCode: 204; +}; + +/** + * Contains response data for the queryEntities operation. + */ +export type TableQueryEntitiesResponse = TableEntityQueryResponse & TableQueryEntitiesHeaders & { + /** + * The response status code. + */ + statusCode: 200; +}; + +/** + * Contains response data for the queryEntitiesWithPartitionAndRowKey operation. + */ +export type TableQueryEntitiesWithPartitionAndRowKeyResponse = TableEntityQueryResponse & TableQueryEntitiesWithPartitionAndRowKeyHeaders & { + /** + * The response status code. + */ + statusCode: 200; +}; + +/** + * Contains response data for the updateEntity operation. + */ +export type TableUpdateEntityResponse = TableUpdateEntityHeaders & { + /** + * The response status code. + */ + statusCode: 204; +}; + +/** + * Contains response data for the mergeEntity operation. + */ +export type TableMergeEntityResponse = TableMergeEntityHeaders & { + /** + * The response status code. + */ + statusCode: 204; +}; + +/** + * Contains response data for the deleteEntity operation. + */ +export type TableDeleteEntityResponse = TableDeleteEntityHeaders & { + /** + * The response status code. + */ + statusCode: 204; +}; + +/** + * Contains response data for the insertEntity operation. + */ +export type TableInsertEntityResponse = { + /** + * The response body properties. + */ + [propertyName: string]: any; +} & TableInsertEntityHeaders & { + /** + * The response status code. + */ + statusCode: 201 | 204; +}; + +/** + * Contains response data for the getAccessPolicy operation. + */ +export type TableGetAccessPolicyResponse = Array & TableGetAccessPolicyHeaders & { + /** + * The response status code. + */ + statusCode: 200; +}; + +/** + * Contains response data for the setAccessPolicy operation. + */ +export type TableSetAccessPolicyResponse = TableSetAccessPolicyHeaders & { + /** + * The response status code. + */ + statusCode: 204; +}; + +/** + * Contains response data for the setProperties operation. + */ +export type ServiceSetPropertiesResponse = ServiceSetPropertiesHeaders & { + /** + * The response status code. + */ + statusCode: 202; +}; + +/** + * Contains response data for the getProperties operation. + */ +export type ServiceGetPropertiesResponse = TableServiceProperties & ServiceGetPropertiesHeaders & { + /** + * The response status code. + */ + statusCode: 200; +}; + +/** + * Contains response data for the getStatistics operation. + */ +export type ServiceGetStatisticsResponse = TableServiceStats & ServiceGetStatisticsHeaders & { + /** + * The response status code. + */ + statusCode: 200; +}; diff --git a/src/table/generated/artifacts/operation.ts b/src/table/generated/artifacts/operation.ts new file mode 100644 index 000000000..7e8215020 --- /dev/null +++ b/src/table/generated/artifacts/operation.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is regenerated. + */ + +export enum Operation { + Table_Query, + Table_Create, + Table_Delete, + Table_QueryEntities, + Table_QueryEntitiesWithPartitionAndRowKey, + Table_UpdateEntity, + Table_MergeEntity, + Table_DeleteEntity, + Table_InsertEntity, + Table_GetAccessPolicy, + Table_SetAccessPolicy, + Service_SetProperties, + Service_GetProperties, + Service_GetStatistics, +} +export default Operation; diff --git a/src/table/generated/artifacts/parameters.ts b/src/table/generated/artifacts/parameters.ts new file mode 100644 index 000000000..920ab25ab --- /dev/null +++ b/src/table/generated/artifacts/parameters.ts @@ -0,0 +1,278 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ + +// tslint:disable:quotemark +// tslint:disable:object-literal-sort-keys + +import * as msRest from "@azure/ms-rest-js"; + +export const comp0: msRest.OperationQueryParameter = { + parameterPath: "comp", + mapper: { + required: true, + isConstant: true, + serializedName: "comp", + defaultValue: 'acl', + type: { + name: "String" + } + } +}; +export const comp1: msRest.OperationQueryParameter = { + parameterPath: "comp", + mapper: { + required: true, + isConstant: true, + serializedName: "comp", + defaultValue: 'properties', + type: { + name: "String" + } + } +}; +export const comp2: msRest.OperationQueryParameter = { + parameterPath: "comp", + mapper: { + required: true, + isConstant: true, + serializedName: "comp", + defaultValue: 'stats', + type: { + name: "String" + } + } +}; +export const dataServiceVersion: msRest.OperationParameter = { + parameterPath: [ + "options", + "dataServiceVersion" + ], + mapper: { + serializedName: "DataServiceVersion", + type: { + name: "String" + } + } +}; +export const filter: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "queryOptions", + "filter" + ], + mapper: { + serializedName: "$filter", + type: { + name: "String" + } + } +}; +export const format: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "queryOptions", + "format" + ], + mapper: { + serializedName: "$format", + type: { + name: "String" + } + } +}; +export const ifMatch0: msRest.OperationParameter = { + parameterPath: [ + "options", + "ifMatch" + ], + mapper: { + serializedName: "If-Match", + type: { + name: "String" + } + } +}; +export const ifMatch1: msRest.OperationParameter = { + parameterPath: "ifMatch", + mapper: { + required: true, + serializedName: "If-Match", + type: { + name: "String" + } + } +}; +export const nextPartitionKey: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "nextPartitionKey" + ], + mapper: { + serializedName: "NextPartitionKey", + type: { + name: "String" + } + } +}; +export const nextRowKey: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "nextRowKey" + ], + mapper: { + serializedName: "NextRowKey", + type: { + name: "String" + } + } +}; +export const nextTableName: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "nextTableName" + ], + mapper: { + serializedName: "NextTableName", + type: { + name: "String" + } + } +}; +export const partitionKey: msRest.OperationURLParameter = { + parameterPath: "partitionKey", + mapper: { + required: true, + serializedName: "partitionKey", + type: { + name: "String" + } + } +}; +export const requestId: msRest.OperationParameter = { + parameterPath: [ + "options", + "requestId" + ], + mapper: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + } +}; +export const responsePreference: msRest.OperationParameter = { + parameterPath: [ + "options", + "responsePreference" + ], + mapper: { + serializedName: "Prefer", + type: { + name: "String" + } + } +}; +export const restype: msRest.OperationQueryParameter = { + parameterPath: "restype", + mapper: { + required: true, + isConstant: true, + serializedName: "restype", + defaultValue: 'service', + type: { + name: "String" + } + } +}; +export const rowKey: msRest.OperationURLParameter = { + parameterPath: "rowKey", + mapper: { + required: true, + serializedName: "rowKey", + type: { + name: "String" + } + } +}; +export const select: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "queryOptions", + "select" + ], + mapper: { + serializedName: "$select", + type: { + name: "String" + } + } +}; +export const table: msRest.OperationURLParameter = { + parameterPath: "table", + mapper: { + required: true, + serializedName: "table", + type: { + name: "String" + } + } +}; +export const timeout: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "timeout" + ], + mapper: { + serializedName: "timeout", + constraints: { + InclusiveMinimum: 0 + }, + type: { + name: "Number" + } + } +}; +export const top: msRest.OperationQueryParameter = { + parameterPath: [ + "options", + "queryOptions", + "top" + ], + mapper: { + serializedName: "$top", + constraints: { + InclusiveMinimum: 0 + }, + type: { + name: "Number" + } + } +}; +export const url: msRest.OperationURLParameter = { + parameterPath: "url", + mapper: { + required: true, + serializedName: "url", + defaultValue: '', + type: { + name: "String" + } + }, + skipEncoding: true +}; +export const version: msRest.OperationParameter = { + parameterPath: "version", + mapper: { + serializedName: "x-ms-version", + type: { + name: "String" + } + } +}; diff --git a/src/table/generated/artifacts/specifications.ts b/src/table/generated/artifacts/specifications.ts new file mode 100644 index 000000000..7bce93104 --- /dev/null +++ b/src/table/generated/artifacts/specifications.ts @@ -0,0 +1,558 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ +// tslint:disable:object-literal-sort-keys + +import * as msRest from "@azure/ms-rest-js"; + +import * as Mappers from "./mappers"; +import { Operation } from "./operation"; +import * as Parameters from "./parameters"; + +const serializer = new msRest.Serializer(Mappers, true); +// specifications for new method group start +const tableQueryOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + path: "Tables", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.nextTableName, + Parameters.format, + Parameters.top, + Parameters.select, + Parameters.filter + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion + ], + responses: { + 200: { + bodyMapper: Mappers.TableQueryResponse, + headersMapper: Mappers.TableQueryHeaders + }, + default: {} + }, + isXML: true, + serializer +}; + +const tableCreateOperationSpec: msRest.OperationSpec = { + httpMethod: "POST", + path: "Tables", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.format + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion, + Parameters.responsePreference + ], + requestBody: { + parameterPath: "tableProperties", + mapper: { + ...Mappers.TableProperties, + required: true + } + }, + contentType: "application/json;odata=nometadata; charset=utf-8", + responses: { + 201: { + bodyMapper: Mappers.TableResponse, + headersMapper: Mappers.TableCreateHeaders + }, + 204: { + headersMapper: Mappers.TableCreateHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableDeleteOperationSpec: msRest.OperationSpec = { + httpMethod: "DELETE", + path: "Tables('{table}')", + urlParameters: [ + Parameters.url, + Parameters.table + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 204: { + headersMapper: Mappers.TableDeleteHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableQueryEntitiesOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + path: "{table}()", + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.nextPartitionKey, + Parameters.nextRowKey, + Parameters.format, + Parameters.top, + Parameters.select, + Parameters.filter + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion + ], + responses: { + 200: { + bodyMapper: Mappers.TableEntityQueryResponse, + headersMapper: Mappers.TableQueryEntitiesHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableQueryEntitiesWithPartitionAndRowKeyOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + path: "{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", + urlParameters: [ + Parameters.url, + Parameters.table, + Parameters.partitionKey, + Parameters.rowKey + ], + queryParameters: [ + Parameters.timeout, + Parameters.format, + Parameters.select, + Parameters.filter + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion + ], + responses: { + 200: { + bodyMapper: Mappers.TableEntityQueryResponse, + headersMapper: Mappers.TableQueryEntitiesWithPartitionAndRowKeyHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableUpdateEntityOperationSpec: msRest.OperationSpec = { + httpMethod: "PUT", + path: "{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", + urlParameters: [ + Parameters.url, + Parameters.table, + Parameters.partitionKey, + Parameters.rowKey + ], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion, + Parameters.ifMatch0 + ], + requestBody: { + parameterPath: [ + "options", + "tableEntityProperties" + ], + mapper: { + serializedName: "tableEntityProperties", + type: { + name: "Dictionary", + value: { + type: { + name: "Object" + } + } + } + } + }, + responses: { + 204: { + headersMapper: Mappers.TableUpdateEntityHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableMergeEntityOperationSpec: msRest.OperationSpec = { + httpMethod: "PATCH", + path: "{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", + urlParameters: [ + Parameters.url, + Parameters.table, + Parameters.partitionKey, + Parameters.rowKey + ], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion, + Parameters.ifMatch0 + ], + requestBody: { + parameterPath: [ + "options", + "tableEntityProperties" + ], + mapper: { + serializedName: "tableEntityProperties", + type: { + name: "Dictionary", + value: { + type: { + name: "Object" + } + } + } + } + }, + responses: { + 204: { + headersMapper: Mappers.TableMergeEntityHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableDeleteEntityOperationSpec: msRest.OperationSpec = { + httpMethod: "DELETE", + path: "{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", + urlParameters: [ + Parameters.url, + Parameters.table, + Parameters.partitionKey, + Parameters.rowKey + ], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion, + Parameters.ifMatch1 + ], + responses: { + 204: { + headersMapper: Mappers.TableDeleteEntityHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableInsertEntityOperationSpec: msRest.OperationSpec = { + httpMethod: "POST", + path: "{table}", + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion, + Parameters.responsePreference + ], + requestBody: { + parameterPath: [ + "options", + "tableEntityProperties" + ], + mapper: { + serializedName: "tableEntityProperties", + type: { + name: "Dictionary", + value: { + type: { + name: "Object" + } + } + } + } + }, + contentType: "application/json;odata=nometadata; charset=utf-8", + responses: { + 201: { + bodyMapper: { + type: { + name: "Dictionary", + value: { + type: { + name: "Object" + } + } + } + }, + headersMapper: Mappers.TableInsertEntityHeaders + }, + 204: { + headersMapper: Mappers.TableInsertEntityHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + path: "{table}", + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp0 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: { + xmlElementName: "SignedIdentifier", + serializedName: "SignedIdentifiers", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "SignedIdentifier" + } + } + } + }, + headersMapper: Mappers.TableGetAccessPolicyHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { + httpMethod: "PUT", + path: "{table}", + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp0 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + requestBody: { + parameterPath: [ + "options", + "tableAcl" + ], + mapper: { + xmlName: "SignedIdentifiers", + xmlElementName: "SignedIdentifier", + serializedName: "tableAcl", + type: { + name: "Sequence", + element: { + type: { + name: "Composite", + className: "SignedIdentifier" + } + } + } + } + }, + contentType: "application/xml; charset=utf-8", + responses: { + 204: { + headersMapper: Mappers.TableSetAccessPolicyHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +// specifications for new method group start +const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { + httpMethod: "PUT", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp1 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + requestBody: { + parameterPath: "tableServiceProperties", + mapper: { + ...Mappers.TableServiceProperties, + required: true + } + }, + contentType: "application/xml; charset=utf-8", + responses: { + 202: { + headersMapper: Mappers.ServiceSetPropertiesHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp1 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: Mappers.TableServiceProperties, + headersMapper: Mappers.ServiceGetPropertiesHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const serviceGetStatisticsOperationSpec: msRest.OperationSpec = { + httpMethod: "GET", + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp2 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], + responses: { + 200: { + bodyMapper: Mappers.TableServiceStats, + headersMapper: Mappers.ServiceGetStatisticsHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + +const Specifications: { [key: number]: msRest.OperationSpec } = {}; +Specifications[Operation.Table_Query] = tableQueryOperationSpec; +Specifications[Operation.Table_Create] = tableCreateOperationSpec; +Specifications[Operation.Table_Delete] = tableDeleteOperationSpec; +Specifications[Operation.Table_QueryEntities] = tableQueryEntitiesOperationSpec; +Specifications[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = + tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; +Specifications[Operation.Table_UpdateEntity] = tableUpdateEntityOperationSpec; +Specifications[Operation.Table_MergeEntity] = tableMergeEntityOperationSpec; +Specifications[Operation.Table_DeleteEntity] = tableDeleteEntityOperationSpec; +Specifications[Operation.Table_InsertEntity] = tableInsertEntityOperationSpec; +Specifications[Operation.Table_GetAccessPolicy] = tableGetAccessPolicyOperationSpec; +Specifications[Operation.Table_SetAccessPolicy] = tableSetAccessPolicyOperationSpec; +Specifications[Operation.Service_SetProperties] = serviceSetPropertiesOperationSpec; +Specifications[Operation.Service_GetProperties] = serviceGetPropertiesOperationSpec; +Specifications[Operation.Service_GetStatistics] = serviceGetStatisticsOperationSpec; +export default Specifications; diff --git a/src/table/generated/errors/DeserializationError.ts b/src/table/generated/errors/DeserializationError.ts new file mode 100644 index 000000000..651ed97c4 --- /dev/null +++ b/src/table/generated/errors/DeserializationError.ts @@ -0,0 +1,8 @@ +import MiddlewareError from "./MiddlewareError"; + +export default class DeserializationError extends MiddlewareError { + public constructor(message: string) { + super(400, message); + this.name = "DeserializationError"; + } +} diff --git a/src/table/generated/errors/MiddlewareError.ts b/src/table/generated/errors/MiddlewareError.ts new file mode 100644 index 000000000..3785f445d --- /dev/null +++ b/src/table/generated/errors/MiddlewareError.ts @@ -0,0 +1,29 @@ +import { OutgoingHttpHeaders } from "http"; + +export default class MiddlewareError extends Error { + /** + * Creates an instance of MiddlewareError. + * + * @param {number} statusCode HTTP response status code + * @param {string} message Error message + * @param {string} [statusMessage] HTTP response status message + * @param {OutgoingHttpHeaders} [headers] HTTP response headers + * @param {string} [body] HTTP response body + * @param {string} [contentType] HTTP contentType + * @memberof MiddlewareError + */ + constructor( + public readonly statusCode: number, + public readonly message: string, + public readonly statusMessage?: string, + public readonly headers?: OutgoingHttpHeaders, + public readonly body?: string, + public readonly contentType?: string + ) { + super(message); + // https://stackoverflow.com/questions/31626231/custom-error-class-in-typescript + Object.setPrototypeOf(this, MiddlewareError.prototype); + + this.name = "MiddlewareError"; + } +} diff --git a/src/table/generated/errors/OperationMismatchError.ts b/src/table/generated/errors/OperationMismatchError.ts new file mode 100644 index 000000000..f05004820 --- /dev/null +++ b/src/table/generated/errors/OperationMismatchError.ts @@ -0,0 +1,11 @@ +import MiddlewareError from "./MiddlewareError"; + +export default class OperationMismatchError extends MiddlewareError { + public constructor() { + super( + 500, + "No operation provided in context, please make sure dispatchMiddleware is properly used." + ); + this.name = "OperationMismatchError"; + } +} diff --git a/src/table/generated/errors/UnsupportedRequestError.ts b/src/table/generated/errors/UnsupportedRequestError.ts new file mode 100644 index 000000000..bdafb4839 --- /dev/null +++ b/src/table/generated/errors/UnsupportedRequestError.ts @@ -0,0 +1,11 @@ +import MiddlewareError from "./MiddlewareError"; + +export default class UnsupportedRequestError extends MiddlewareError { + public constructor() { + super( + 400, + "Incoming URL doesn't match any of swagger defined request patterns." + ); + this.name = "UnsupportedRequestError"; + } +} diff --git a/src/table/generated/handlers/IHandlers.ts b/src/table/generated/handlers/IHandlers.ts new file mode 100644 index 000000000..5b6a36fd0 --- /dev/null +++ b/src/table/generated/handlers/IHandlers.ts @@ -0,0 +1,9 @@ +// tslint:disable:ordered-imports +import ITableHandler from "./ITableHandler"; +import IServiceHandler from "./IServiceHandler"; + +export interface IHandlers { + tableHandler: ITableHandler; + serviceHandler: IServiceHandler; +} +export default IHandlers; diff --git a/src/table/generated/handlers/IServiceHandler.ts b/src/table/generated/handlers/IServiceHandler.ts new file mode 100644 index 000000000..ff6b39255 --- /dev/null +++ b/src/table/generated/handlers/IServiceHandler.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ +// tslint:disable:max-line-length + +import * as Models from "../artifacts/models"; +import Context from "../Context"; + +export default interface IServiceHandler { + setProperties(tableServiceProperties: Models.TableServiceProperties, options: Models.ServiceSetPropertiesOptionalParams, context: Context): Promise; + getProperties(options: Models.ServiceGetPropertiesOptionalParams, context: Context): Promise; + getStatistics(options: Models.ServiceGetStatisticsOptionalParams, context: Context): Promise; +} diff --git a/src/table/generated/handlers/ITableHandler.ts b/src/table/generated/handlers/ITableHandler.ts new file mode 100644 index 000000000..ce47d37dd --- /dev/null +++ b/src/table/generated/handlers/ITableHandler.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + * + * Code generated by Microsoft (R) AutoRest Code Generator. + * Changes may cause incorrect behavior and will be lost if the code is + * regenerated. + */ +// tslint:disable:max-line-length + +import * as Models from "../artifacts/models"; +import Context from "../Context"; + +export default interface ITableHandler { + query(options: Models.TableQueryOptionalParams, context: Context): Promise; + create(tableProperties: Models.TableProperties, options: Models.TableCreateOptionalParams, context: Context): Promise; + delete(table: string, options: Models.TableDeleteMethodOptionalParams, context: Context): Promise; + queryEntities(table: string, options: Models.TableQueryEntitiesOptionalParams, context: Context): Promise; + queryEntitiesWithPartitionAndRowKey(table: string, partitionKey: string, rowKey: string, options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, context: Context): Promise; + updateEntity(table: string, partitionKey: string, rowKey: string, options: Models.TableUpdateEntityOptionalParams, context: Context): Promise; + mergeEntity(table: string, partitionKey: string, rowKey: string, options: Models.TableMergeEntityOptionalParams, context: Context): Promise; + deleteEntity(table: string, partitionKey: string, rowKey: string, ifMatch: string, options: Models.TableDeleteEntityOptionalParams, context: Context): Promise; + insertEntity(table: string, options: Models.TableInsertEntityOptionalParams, context: Context): Promise; + getAccessPolicy(table: string, options: Models.TableGetAccessPolicyOptionalParams, context: Context): Promise; + setAccessPolicy(table: string, options: Models.TableSetAccessPolicyOptionalParams, context: Context): Promise; +} diff --git a/src/table/generated/handlers/handlerMappers.ts b/src/table/generated/handlers/handlerMappers.ts new file mode 100644 index 000000000..f1545df96 --- /dev/null +++ b/src/table/generated/handlers/handlerMappers.ts @@ -0,0 +1,134 @@ +import Operation from "../artifacts/operation"; + +// tslint:disable:one-line + +export interface IHandlerPath { + handler: string; + method: string; + arguments: string[]; +} + +const operationHandlerMapping: {[key: number]: IHandlerPath} = {}; + +operationHandlerMapping[Operation.Table_Query] = { + arguments: [ + "options" + ], + handler: "tableHandler", + method: "query" +}; +operationHandlerMapping[Operation.Table_Create] = { + arguments: [ + "tableProperties", + "options" + ], + handler: "tableHandler", + method: "create" +}; +operationHandlerMapping[Operation.Table_Delete] = { + arguments: [ + "table", + "options" + ], + handler: "tableHandler", + method: "delete" +}; +operationHandlerMapping[Operation.Table_QueryEntities] = { + arguments: [ + "table", + "options" + ], + handler: "tableHandler", + method: "queryEntities" +}; +operationHandlerMapping[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = { + arguments: [ + "table", + "partitionKey", + "rowKey", + "options" + ], + handler: "tableHandler", + method: "queryEntitiesWithPartitionAndRowKey" +}; +operationHandlerMapping[Operation.Table_UpdateEntity] = { + arguments: [ + "table", + "partitionKey", + "rowKey", + "options" + ], + handler: "tableHandler", + method: "updateEntity" +}; +operationHandlerMapping[Operation.Table_MergeEntity] = { + arguments: [ + "table", + "partitionKey", + "rowKey", + "options" + ], + handler: "tableHandler", + method: "mergeEntity" +}; +operationHandlerMapping[Operation.Table_DeleteEntity] = { + arguments: [ + "table", + "partitionKey", + "rowKey", + "ifMatch", + "options" + ], + handler: "tableHandler", + method: "deleteEntity" +}; +operationHandlerMapping[Operation.Table_InsertEntity] = { + arguments: [ + "table", + "options" + ], + handler: "tableHandler", + method: "insertEntity" +}; +operationHandlerMapping[Operation.Table_GetAccessPolicy] = { + arguments: [ + "table", + "options" + ], + handler: "tableHandler", + method: "getAccessPolicy" +}; +operationHandlerMapping[Operation.Table_SetAccessPolicy] = { + arguments: [ + "table", + "options" + ], + handler: "tableHandler", + method: "setAccessPolicy" +}; +operationHandlerMapping[Operation.Service_SetProperties] = { + arguments: [ + "tableServiceProperties", + "options" + ], + handler: "serviceHandler", + method: "setProperties" +}; +operationHandlerMapping[Operation.Service_GetProperties] = { + arguments: [ + "options" + ], + handler: "serviceHandler", + method: "getProperties" +}; +operationHandlerMapping[Operation.Service_GetStatistics] = { + arguments: [ + "options" + ], + handler: "serviceHandler", + method: "getStatistics" +}; +function getHandlerByOperation(operation: Operation): IHandlerPath | undefined { + return operationHandlerMapping[operation]; +} +export default getHandlerByOperation; diff --git a/src/table/generated/middleware/HandlerMiddlewareFactory.ts b/src/table/generated/middleware/HandlerMiddlewareFactory.ts new file mode 100644 index 000000000..b78ac9ea5 --- /dev/null +++ b/src/table/generated/middleware/HandlerMiddlewareFactory.ts @@ -0,0 +1,90 @@ +import Operation from "../artifacts/operation"; +import Specifications from "../artifacts/specifications"; +import Context from "../Context"; +import OperationMismatchError from "../errors/OperationMismatchError"; +import getHandlerByOperation from "../handlers/handlerMappers"; +import IHandlers from "../handlers/IHandlers"; +import { NextFunction } from "../MiddlewareFactory"; +import ILogger from "../utils/ILogger"; + +/** + * Auto generated. HandlerMiddlewareFactory will accept handlers and create handler middleware. + * + * @export + * @class HandlerMiddlewareFactory + */ +export default class HandlerMiddlewareFactory { + /** + * Creates an instance of HandlerMiddlewareFactory. + * Accept handlers and create handler middleware. + * + * @param {IHandlers} handlers Handlers implemented handler interfaces + * @param {ILogger} logger A valid logger + * @memberof HandlerMiddlewareFactory + */ + constructor( + private readonly handlers: IHandlers, + private readonly logger: ILogger + ) {} + + /** + * Creates a handler middleware from input handlers. + * + * @memberof HandlerMiddlewareFactory + */ + public createHandlerMiddleware(): ( + context: Context, + next: NextFunction + ) => void { + return (context: Context, next: NextFunction) => { + this.logger.info( + `HandlerMiddleware: DeserializedParameters=${JSON.stringify( + context.handlerParameters, + (key, value) => { + if (key === "body") { + return "ReadableStream"; + } + return value; + } + )}`, + context.contextID + ); + + if (context.operation === undefined) { + const handlerError = new OperationMismatchError(); + this.logger.error( + `HandlerMiddleware: ${handlerError.message}`, + context.contextID + ); + return next(handlerError); + } + + if (Specifications[context.operation] === undefined) { + this.logger.warn( + `HandlerMiddleware: cannot find handler for operation ${ + Operation[context.operation] + }` + ); + } + + // We assume handlerPath always exists for every generated operation in generated code + const handlerPath = getHandlerByOperation(context.operation)!; + + const args = []; + for (const arg of handlerPath.arguments) { + args.push(context.handlerParameters![arg]); + } + args.push(context); + + const handler = (this.handlers as any)[handlerPath.handler]; + const handlerMethod = handler[handlerPath.method] as () => Promise; + handlerMethod + .apply(handler, args as any) + .then((response: any) => { + context.handlerResponses = response; + }) + .then(next) + .catch(next); + }; + } +} diff --git a/src/table/generated/middleware/deserializer.middleware.ts b/src/table/generated/middleware/deserializer.middleware.ts new file mode 100644 index 000000000..8042fdf49 --- /dev/null +++ b/src/table/generated/middleware/deserializer.middleware.ts @@ -0,0 +1,59 @@ +import Operation from "../artifacts/operation"; +import Specifications from "../artifacts/specifications"; +import Context from "../Context"; +import DeserializationError from "../errors/DeserializationError"; +import OperationMismatchError from "../errors/OperationMismatchError"; +import IRequest from "../IRequest"; +import { NextFunction } from "../MiddlewareFactory"; +import ILogger from "../utils/ILogger"; +import { deserialize } from "../utils/serializer"; + +/** + * Deserializer Middleware. Deserialize incoming HTTP request into models. + * + * @export + * @param {Context} context + * @param {IRequest} req An IRequest object + * @param {NextFunction} next An next callback or promise + * @param {ILogger} logger A valid logger + * @returns {void} + */ +export default function deserializerMiddleware( + context: Context, + req: IRequest, + next: NextFunction, + logger: ILogger +): void { + logger.verbose( + `DeserializerMiddleware: Start deserializing...`, + context.contextID + ); + + if (context.operation === undefined) { + const handlerError = new OperationMismatchError(); + logger.error( + `DeserializerMiddleware: ${handlerError.message}`, + context.contextID + ); + return next(handlerError); + } + + if (Specifications[context.operation] === undefined) { + logger.warn( + `DeserializerMiddleware: Cannot find deserializer for operation ${ + Operation[context.operation] + }` + ); + } + + deserialize(context, req, Specifications[context.operation], logger) + .then(parameters => { + context.handlerParameters = parameters; + }) + .then(next) + .catch(err => { + const deserializationError = new DeserializationError(err.message); + deserializationError.stack = err.stack; + next(deserializationError); + }); +} diff --git a/src/table/generated/middleware/dispatch.middleware.ts b/src/table/generated/middleware/dispatch.middleware.ts new file mode 100644 index 000000000..b287f82e8 --- /dev/null +++ b/src/table/generated/middleware/dispatch.middleware.ts @@ -0,0 +1,176 @@ +import * as msRest from "@azure/ms-rest-js"; + +import Operation from "../artifacts/operation"; +import Specifications from "../artifacts/specifications"; +import Context from "../Context"; +import UnsupportedRequestError from "../errors/UnsupportedRequestError"; +import IRequest from "../IRequest"; +import { NextFunction } from "../MiddlewareFactory"; +import ILogger from "../utils/ILogger"; +import { isURITemplateMatch } from "../utils/utils"; + +/** + * Dispatch Middleware will try to find out which operation of current HTTP request belongs to, + * by going through request specifications. Operation enum will be assigned to context object. + * Make sure dispatchMiddleware is triggered before other generated middleware. + * + * TODO: Add support for API priorities to deal with both matched APIs + * + * @export + * @param {Context} context Context object + * @param {IRequest} req An request object + * @param {NextFunction} next A callback + * @param {ILogger} logger A valid logger + * @returns {void} + */ +export default function dispatchMiddleware( + context: Context, + req: IRequest, + next: NextFunction, + logger: ILogger +): void { + logger.verbose( + `DispatchMiddleware: Dispatching request...`, + context.contextID + ); + + // Sometimes, more than one operations specifications are all valid against current request + // Such as a SetContainerMetadata request will fit both CreateContainer and SetContainerMetadata specifications + // We need to avoid this kind of situation when define swagger + // However, following code will try to find most suitable operation by selecting operation which + // have most required conditions met + let conditionsMet: number = -1; + + for (const key in Operation) { + if (Operation.hasOwnProperty(key)) { + const operation = parseInt(key, 10); + const res = isRequestAgainstOperation( + req, + Specifications[operation], + context.dispatchPattern + ); + if (res[0] && res[1] > conditionsMet) { + context.operation = operation; + conditionsMet = res[1]; + } + } + } + + if (context.operation === undefined) { + const handlerError = new UnsupportedRequestError(); + logger.error( + `DispatchMiddleware: ${handlerError.message}`, + context.contextID + ); + return next(handlerError); + } + + logger.info( + `DispatchMiddleware: Operation=${Operation[context.operation]}`, + context.contextID + ); + + next(); +} + +/** + * Validation whether current request meets request operation specification. + * + * @param {IRequest} req + * @param {msRest.OperationSpec} spec + * @returns {[boolean, number]} Tuple includes validation result and number of met required conditions + */ +function isRequestAgainstOperation( + req: IRequest, + spec: msRest.OperationSpec, + dispatchPathPattern?: string +): [boolean, number] { + let metConditionsNum = 0; + if (req === undefined || spec === undefined) { + return [false, metConditionsNum]; + } + + // Validate HTTP method + if (req.getMethod() !== spec.httpMethod) { + return [false, metConditionsNum++]; + } + + // Validate URL path + const path = spec.path + ? spec.path.startsWith("/") + ? spec.path + : `/${spec.path}` + : "/"; + if ( + !isURITemplateMatch( + // Use dispatch path with priority + dispatchPathPattern !== undefined ? dispatchPathPattern : req.getPath(), + path + ) + ) { + return [false, metConditionsNum++]; + } + + // Validate required queryParameters + for (const queryParameter of spec.queryParameters || []) { + if (queryParameter.mapper.required) { + const queryValue = req.getQuery( + queryParameter.mapper.serializedName || "" + ); + if (queryValue === undefined) { + return [false, metConditionsNum]; + } + + if ( + queryParameter.mapper.type.name === "Enum" && + queryParameter.mapper.type.allowedValues.findIndex(val => { + return val === queryValue; + }) < 0 + ) { + return [false, metConditionsNum]; + } + + if ( + queryParameter.mapper.isConstant && + queryParameter.mapper.defaultValue !== queryValue + ) { + return [false, metConditionsNum]; + } + + metConditionsNum++; + } + } + + // Validate required header parameters + for (const headerParameter of spec.headerParameters || []) { + if (headerParameter.mapper.required) { + const headerValue = req.getHeader( + headerParameter.mapper.serializedName || "" + ); + if (headerValue === undefined) { + return [false, metConditionsNum]; + } + + if ( + headerParameter.mapper.type.name === "Enum" && + headerParameter.mapper.type.allowedValues.findIndex(val => { + return val === headerValue; + }) < 0 + ) { + return [false, metConditionsNum]; + } + + if ( + headerParameter.mapper.isConstant && + `${headerParameter.mapper.defaultValue || ""}`.toLowerCase() !== + headerValue.toLowerCase() + ) { + return [false, metConditionsNum]; + } + + metConditionsNum++; + } + } + + return [true, metConditionsNum]; +} diff --git a/src/table/generated/middleware/end.middleware.ts b/src/table/generated/middleware/end.middleware.ts new file mode 100644 index 000000000..cc75e6b8b --- /dev/null +++ b/src/table/generated/middleware/end.middleware.ts @@ -0,0 +1,32 @@ +import Context from "../Context"; +import IResponse from "../IResponse"; +import ILogger from "../utils/ILogger"; + +/** + * End middleware is used to send out final HTTP response. + * + * @export + * @param {Context} context + * @param {Request} req An express compatible Request object + * @param {Response} res An express compatible Response object + * @param {ILogger} logger A valid logger + */ +export default function endMiddleware( + context: Context, + res: IResponse, + logger: ILogger, +): void { + const totalTimeInMS = context.startTime + ? new Date().getTime() - context.startTime.getTime() + : undefined; + + logger.info( + // tslint:disable-next-line:max-line-length + `EndMiddleware: End response. TotalTimeInMS=${totalTimeInMS} StatusCode=${res.getStatusCode()} StatusMessage=${res.getStatusMessage()} Headers=${JSON.stringify( + res.getHeaders() + )}`, + context.contextID + ); + + res.getBodyStream().end(); +} diff --git a/src/table/generated/middleware/error.middleware.ts b/src/table/generated/middleware/error.middleware.ts new file mode 100644 index 000000000..e923e0c65 --- /dev/null +++ b/src/table/generated/middleware/error.middleware.ts @@ -0,0 +1,134 @@ +import Context from "../Context"; +import MiddlewareError from "../errors/MiddlewareError"; +import IRequest from "../IRequest"; +import IResponse from "../IResponse"; +import { NextFunction } from "../MiddlewareFactory"; +import ILogger from "../utils/ILogger"; + +/** + * ErrorMiddleware handles following 2 kinds of errors thrown from previous middleware or handlers: + * + * 1. MiddlewareError will be serialized. + * This includes most of expected errors, such as 4XX or some 5xx errors are MiddlewareError. + * + * 2. Other unexpected errors will be serialized to 500 Internal Server error directly. + * Every this kind of error should be carefully checked, and consider to handle it as a MiddlewareError. + * + * @export + * @param {Context} context + * @param {(MiddlewareError | Error)} err A MiddlewareError or Error object + * @param {Request} req An express compatible Request object + * @param {Response} res An express compatible Response object + * @param {NextFunction} next An express middleware next callback + * @param {ILogger} logger A valid logger + * @returns {void} + */ +export default function errorMiddleware( + context: Context, + err: MiddlewareError | Error, + req: IRequest, + res: IResponse, + next: NextFunction, + logger: ILogger +): void { + if (res.headersSent()) { + logger.warn( + `Error middleware received an error, but response.headersSent is true, pass error to next middleware`, + context.contextID + ); + return next(err); + } + + // Only handle ServerError, for other customized error types hand over to + // other error handlers. + if (err instanceof MiddlewareError) { + logger.error( + `ErrorMiddleware: Received a MiddlewareError, fill error information to HTTP response`, + context.contextID + ); + + logger.error( + `ErrorMiddleware: ErrorName=${err.name} ErrorMessage=${ + err.message + } ErrorHTTPStatusCode=${err.statusCode} ErrorHTTPStatusMessage=${ + err.statusMessage + } ErrorHTTPHeaders=${JSON.stringify( + err.headers + )} ErrorHTTPBody=${JSON.stringify(err.body)} ErrorStack=${JSON.stringify( + err.stack + )}`, + context.contextID + ); + + logger.error( + `ErrorMiddleware: Set HTTP code: ${err.statusCode}`, + context.contextID + ); + + res.setStatusCode(err.statusCode); + if (err.statusMessage) { + logger.error( + `ErrorMiddleware: Set HTTP status message: ${err.statusMessage}`, + context.contextID + ); + res.setStatusMessage(err.statusMessage); + } + + if (err.headers) { + for (const key in err.headers) { + if (err.headers.hasOwnProperty(key)) { + const value = err.headers[key]; + if (value) { + logger.error( + `ErrorMiddleware: Set HTTP Header: ${key}=${value}`, + context.contextID + ); + res.setHeader(key, value); + } + } + } + } + + if (err.contentType && req.getMethod() !== "HEAD") { + logger.error( + `ErrorMiddleware: Set content type: ${err.contentType}`, + context.contextID + ); + res.setContentType(err.contentType); + } + + logger.error( + `ErrorMiddleware: Set HTTP body: ${JSON.stringify(err.body)}`, + context.contextID + ); + if (err.body && req.getMethod() !== "HEAD") { + res.getBodyStream().write(err.body); + } + } else if (err instanceof Error) { + logger.error( + `ErrorMiddleware: Received an error, fill error information to HTTP response`, + context.contextID + ); + logger.error( + `ErrorMiddleware: ErrorName=${err.name} ErrorMessage=${ + err.message + } ErrorStack=${JSON.stringify(err.stack)}`, + context.contextID + ); + logger.error(`ErrorMiddleware: Set HTTP code: ${500}`, context.contextID); + res.setStatusCode(500); + + // logger.error( + // `ErrorMiddleware: Set error message: ${err.message}`, + // context.contextID + // ); + // res.getBodyStream().write(err.message); + } else { + logger.warn( + `ErrorMiddleware: Received unhandled error object`, + context.contextID + ); + } + + next(); +} diff --git a/src/table/generated/middleware/serializer.middleware.ts b/src/table/generated/middleware/serializer.middleware.ts new file mode 100644 index 000000000..6cf29fdaf --- /dev/null +++ b/src/table/generated/middleware/serializer.middleware.ts @@ -0,0 +1,57 @@ +import Operation from "../artifacts/operation"; +import Specifications from "../artifacts/specifications"; +import Context from "../Context"; +import OperationMismatchError from "../errors/OperationMismatchError"; +import IResponse from "../IResponse"; +import { NextFunction } from "../MiddlewareFactory"; +import ILogger from "../utils/ILogger"; +import { serialize } from "../utils/serializer"; + +/** + * SerializerMiddleware will serialize models into HTTP responses. + * + * @export + * @param {Response} res + * @param {NextFunction} next + * @param {ILogger} logger + * @param {Context} context + */ +export default function serializerMiddleware( + context: Context, + res: IResponse, + next: NextFunction, + logger: ILogger +): void { + logger.verbose( + `SerializerMiddleware: Start serializing...`, + context.contextID + ); + + if (context.operation === undefined) { + const handlerError = new OperationMismatchError(); + logger.error( + `SerializerMiddleware: ${handlerError.message}`, + context.contextID + ); + return next(handlerError); + } + + if (Specifications[context.operation] === undefined) { + logger.warn( + `SerializerMiddleware: Cannot find serializer for operation ${ + Operation[context.operation] + }`, + context.contextID + ); + } + + serialize( + context, + res, + Specifications[context.operation], + context.handlerResponses, + logger + ) + .then(next) + .catch(next); +} diff --git a/src/table/generated/utils/ILogger.ts b/src/table/generated/utils/ILogger.ts new file mode 100644 index 000000000..cef94893d --- /dev/null +++ b/src/table/generated/utils/ILogger.ts @@ -0,0 +1,13 @@ +/** + * An interface of logger used by generated code. + * + * @export + * @interface ILogger + */ +export default interface ILogger { + error(message: string, contextID?: string): void; + warn(message: string, contextID?: string): void; + info(message: string, contextID?: string): void; + verbose(message: string, contextID?: string): void; + debug(message: string, contextID?: string): void; +} diff --git a/src/table/generated/utils/serializer.ts b/src/table/generated/utils/serializer.ts new file mode 100644 index 000000000..81aac9a11 --- /dev/null +++ b/src/table/generated/utils/serializer.ts @@ -0,0 +1,353 @@ +import * as msRest from "@azure/ms-rest-js"; + +import * as Mappers from "../artifacts/mappers"; +import Context, { IHandlerParameters } from "../Context"; +import IRequest from "../IRequest"; +import IResponse from "../IResponse"; +import ILogger from "./ILogger"; +import { parseXML, stringifyXML } from "./xml"; + +export declare type ParameterPath = + | string + | string[] + | { + [propertyName: string]: ParameterPath; + }; + +export async function deserialize( + context: Context, + req: IRequest, + spec: msRest.OperationSpec, + logger: ILogger +): Promise { + const parameters: IHandlerParameters = {}; + + // Deserialize query parameters + for (const queryParameter of spec.queryParameters || []) { + if (!queryParameter.mapper.serializedName) { + throw new TypeError( + `QueryParameter mapper doesn't include valid "serializedName"` + ); + } + const queryKey = queryParameter.mapper.serializedName; + let queryValueOriginal: string | string[] | undefined = req.getQuery( + queryKey + ); + + if ( + queryValueOriginal !== undefined && + queryParameter.collectionFormat !== undefined && + queryParameter.mapper.type.name === "Sequence" + ) { + queryValueOriginal = `${queryValueOriginal}`.split( + queryParameter.collectionFormat + ); + } + + const queryValue = spec.serializer.deserialize( + queryParameter.mapper, + queryValueOriginal, + queryKey + ); + + // TODO: Currently validation is only in serialize method, + // remove when adding validateConstraints to deserialize() + // TODO: Make serialize return ServerError according to different validations? + spec.serializer.serialize(queryParameter.mapper, queryValue); + + setParametersValue(parameters, queryParameter.parameterPath, queryValue); + } + + // Deserialize header parameters + for (const headerParameter of spec.headerParameters || []) { + if (!headerParameter.mapper.serializedName) { + throw new TypeError( + `HeaderParameter mapper doesn't include valid "serializedName"` + ); + } + + const headerCollectionPrefix: + | string + | undefined = (headerParameter.mapper as msRest.DictionaryMapper) + .headerCollectionPrefix; + if (headerCollectionPrefix) { + const dictionary: any = {}; + const headers = req.getHeaders(); + for (const headerKey of Object.keys(headers)) { + if ( + headerKey + .toLowerCase() + .startsWith(headerCollectionPrefix.toLocaleLowerCase()) + ) { + // TODO: Validate collection type by serializer + dictionary[ + headerKey.substring(headerCollectionPrefix.length) + ] = spec.serializer.serialize( + (headerParameter.mapper as msRest.DictionaryMapper).type.value, + headers[headerKey], + headerKey + ); + } + } + setParametersValue(parameters, headerParameter.parameterPath, dictionary); + } else { + const headerKey = headerParameter.mapper.serializedName; + const headerValueOriginal = req.getHeader(headerKey); + const headerValue = spec.serializer.deserialize( + headerParameter.mapper, + headerValueOriginal, + headerKey + ); + + // TODO: Currently validation is only in serialize method, + // remove when adding validateConstraints to deserialize() + spec.serializer.serialize(headerParameter.mapper, headerValue); + + setParametersValue( + parameters, + headerParameter.parameterPath, + headerValue + ); + } + } + + // Deserialize body + const bodyParameter = spec.requestBody; + + if (bodyParameter && bodyParameter.mapper.type.name === "Stream") { + setParametersValue(parameters, "body", req.getBodyStream()); + } else if (bodyParameter) { + const jsonContentTypes = ["application/json", "text/json"]; + const xmlContentTypes = ["application/xml", "application/atom+xml"]; + const contentType = req.getHeader("content-type") || ""; + const contentComponents = !contentType + ? [] + : contentType.split(";").map(component => component.toLowerCase()); + + const isRequestWithJSON = contentComponents.some( + component => jsonContentTypes.indexOf(component) !== -1 + ); // TODO + const isRequestWithXML = + spec.isXML || + contentComponents.some( + component => xmlContentTypes.indexOf(component) !== -1 + ); + // const isRequestWithStream = false; + + const body = await readRequestIntoText(req); + logger.debug( + `deserialize(): Raw request body string is ${body}`, + context.contextID + ); + + req.setBody(body); + let parsedBody: object = {}; + if (isRequestWithJSON) { + // read body + parsedBody = JSON.parse(body); + } else if (isRequestWithXML) { + parsedBody = (await parseXML(body)) || {}; + } + + let valueToDeserialize: any = parsedBody; + if ( + spec.isXML && + bodyParameter.mapper.type.name === msRest.MapperType.Sequence + ) { + valueToDeserialize = + typeof valueToDeserialize === "object" + ? valueToDeserialize[bodyParameter.mapper.xmlElementName!] + : []; + } + + parsedBody = spec.serializer.deserialize( + bodyParameter.mapper, + valueToDeserialize, + bodyParameter.mapper.serializedName! + ); + + // Validation purpose only, because only serialize supports validation + // TODO: Inject convenience layer error into deserialize; Drop @azure/ms-rest-js, move logic into generated code + spec.serializer.serialize(bodyParameter.mapper, parsedBody); + + setParametersValue(parameters, bodyParameter.parameterPath, parsedBody); + setParametersValue(parameters, "body", req.getBody()); + } + + return parameters; +} + +async function readRequestIntoText(req: IRequest): Promise { + return new Promise((resolve, reject) => { + const segments: string[] = []; + const bodyStream = req.getBodyStream(); + bodyStream.on("data", buffer => { + segments.push(buffer); + }); + bodyStream.on("error", reject); + bodyStream.on("end", () => { + const joined = segments.join(""); + resolve(joined); + }); + }); +} + +function setParametersValue( + parameters: IHandlerParameters, + parameterPath: ParameterPath, + parameterValue: any +) { + if (typeof parameterPath === "string") { + parameters[parameterPath] = parameterValue; + } else if (Array.isArray(parameterPath)) { + let leafParent = parameters; + for (let i = 0; i < parameterPath.length - 1; i++) { + const currentPropertyName = parameterPath[i]; + if (!leafParent[currentPropertyName]) { + leafParent[currentPropertyName] = {}; + } + leafParent = leafParent[currentPropertyName]; + } + + const lastPropertyName = parameterPath[parameterPath.length - 1]; + leafParent[lastPropertyName] = parameterValue; + } else { + throw new TypeError(`parameterPath is not string or string[]`); + } +} + +export async function serialize( + context: Context, + res: IResponse, + spec: msRest.OperationSpec, + handlerResponse: any, + logger: ILogger +): Promise { + const statusCodeInResponse: number = handlerResponse.statusCode; + res.setStatusCode(statusCodeInResponse); + + const responseSpec = spec.responses[statusCodeInResponse]; + if (!responseSpec) { + throw new TypeError( + `Request specification doesn't include provided response status code` + ); + } + + // Serialize headers + const headerSerializer = new msRest.Serializer(Mappers); + const headersMapper = responseSpec.headersMapper; + if (headersMapper && headersMapper.type.name === "Composite") { + const mappersForAllHeaders = headersMapper.type.modelProperties || {}; + + // Handle headerMapper one by one + for (const key in mappersForAllHeaders) { + if (mappersForAllHeaders.hasOwnProperty(key)) { + const headerMapper = mappersForAllHeaders[key]; + const headerName = headerMapper.serializedName; + const headerValueOriginal = handlerResponse[key]; + const headerValueSerialized = headerSerializer.serialize( + headerMapper, + headerValueOriginal + ); + + // Handle collection of headers starting with same prefix, such as x-ms-meta prefix + const headerCollectionPrefix = (headerMapper as msRest.DictionaryMapper) + .headerCollectionPrefix; + if ( + headerCollectionPrefix !== undefined && + headerValueOriginal !== undefined + ) { + for (const collectionHeaderPartialName in headerValueSerialized) { + if ( + headerValueSerialized.hasOwnProperty(collectionHeaderPartialName) + ) { + const collectionHeaderValueSerialized = + headerValueSerialized[collectionHeaderPartialName]; + const collectionHeaderName = `${headerCollectionPrefix}${collectionHeaderPartialName}`; + if ( + collectionHeaderName && + collectionHeaderValueSerialized !== undefined + ) { + res.setHeader( + collectionHeaderName, + collectionHeaderValueSerialized + ); + } + } + } + } else { + if (headerName && headerValueSerialized !== undefined) { + res.setHeader(headerName, headerValueSerialized); + } + } + } + } + } + + // Serialize XML bodies + if ( + spec.isXML && + responseSpec.bodyMapper && + responseSpec.bodyMapper.type.name !== "Stream" + ) { + let body = spec.serializer.serialize( + responseSpec.bodyMapper!, + handlerResponse + ); + + // When root element is sequence type, should wrap with because serialize() doesn't do that + if (responseSpec.bodyMapper!.type.name === "Sequence") { + const sequenceElementName = responseSpec.bodyMapper!.xmlElementName; + if (sequenceElementName !== undefined) { + const newBody = {} as any; + newBody[sequenceElementName] = body; + body = newBody; + } + } + + const xmlBody = stringifyXML(body, { + rootName: + responseSpec.bodyMapper!.xmlName || + responseSpec.bodyMapper!.serializedName + }); + res.setContentType(`application/xml`); + + // TODO: Should send response in a serializer? + res.getBodyStream().write(xmlBody); + logger.debug( + `Serializer: Raw response body string is ${xmlBody}`, + context.contextID + ); + logger.info(`Serializer: Start returning stream body.`, context.contextID); + } + + // Serialize stream body + // TODO: Move to end middleware for end tracking + if ( + handlerResponse.body && + responseSpec.bodyMapper && + responseSpec.bodyMapper.type.name === "Stream" + ) { + logger.info(`Serializer: Start returning stream body.`, context.contextID); + + await new Promise((resolve, reject) => { + (handlerResponse.body as NodeJS.ReadableStream) + .on("error", reject) + .pipe(res.getBodyStream()) + .on("error", reject) + .on("close", resolve); + }); + + // const totalTimeInMS = context.startTime + // ? new Date().getTime() - context.startTime.getTime() + // : undefined; + + // logger.info( + // tslint:disable-next-line:max-line-length + // `Serializer: End response. TotalTimeInMS=${totalTimeInMS} StatusCode=${res.getStatusCode()} StatusMessage=${res.getStatusMessage()} Headers=${JSON.stringify( + // res.getHeaders() + // )}`, + // context.contextID + // ); + } +} diff --git a/src/table/generated/utils/utils.ts b/src/table/generated/utils/utils.ts new file mode 100644 index 000000000..014377abe --- /dev/null +++ b/src/table/generated/utils/utils.ts @@ -0,0 +1,20 @@ +import URITemplate from "uri-templates"; + +export function isURITemplateMatch(url: string, template: string): boolean { + const uriTemplate = URITemplate(template); + // TODO: Fixing $ parsing issue such as $logs container cannot work in strict mode issue + const result = (uriTemplate.fromUri as any)(url, { strict: true }); + if (result === undefined) { + return false; + } + + for (const key in result) { + if (result.hasOwnProperty(key)) { + const element = result[key]; + if (element === "") { + return false; + } + } + } + return true; +} diff --git a/src/table/generated/utils/xml.ts b/src/table/generated/utils/xml.ts new file mode 100644 index 000000000..676827077 --- /dev/null +++ b/src/table/generated/utils/xml.ts @@ -0,0 +1,41 @@ +import * as xml2js from "xml2js"; + +export function stringifyXML(obj: any, opts?: { rootName?: string }) { + const builder = new xml2js.Builder({ + explicitArray: false, + explicitCharkey: false, + renderOpts: { + pretty: false + }, + rootName: (opts || {}).rootName + }); + return builder.buildObject(obj); +} + +export function parseXML( + str: string, + explicitChildrenWithOrder: boolean = false +): Promise { + const xmlParser = new xml2js.Parser({ + explicitArray: false, + explicitCharkey: false, + explicitRoot: false, + preserveChildrenOrder: explicitChildrenWithOrder, + explicitChildren: explicitChildrenWithOrder, + emptyTag: undefined + }); + return new Promise((resolve, reject) => { + xmlParser.parseString(str, (err?: Error, res?: any) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }); + }); +} + +export function jsonToXML(json: any): string { + const build = new xml2js.Builder(); + return build.buildObject(json); +} diff --git a/src/table/handlers/BaseHandler.ts b/src/table/handlers/BaseHandler.ts new file mode 100644 index 000000000..05e986aeb --- /dev/null +++ b/src/table/handlers/BaseHandler.ts @@ -0,0 +1,17 @@ +import ILogger from "../generated/utils/ILogger"; +import ITableMetadataStore from "../persistence/ITableMetadataStore"; + +/** + * BaseHandler class should maintain a singleton to persistency layer, such as maintain a database connection pool. + * So every inherited classes instances can reuse the persistency layer connection. + * + * @export + * @class BaseHandler + * @implements {IHandler} + */ +export default class BaseHandler { + constructor( + protected readonly metadataStore: ITableMetadataStore, + protected readonly logger: ILogger + ) {} +} diff --git a/src/table/handlers/ServiceHandler.ts b/src/table/handlers/ServiceHandler.ts new file mode 100644 index 000000000..6b12f9a22 --- /dev/null +++ b/src/table/handlers/ServiceHandler.ts @@ -0,0 +1,33 @@ +import NotImplementedError from "../errors/NotImplementedError"; +import * as Models from "../generated/artifacts/models"; +import Context from "../generated/Context"; +import IServiceHandler from "../generated/handlers/IServiceHandler"; +import BaseHandler from "./BaseHandler"; + +export default class ServiceHandler extends BaseHandler + implements IServiceHandler { + public async setProperties( + tableServiceProperties: Models.TableServiceProperties, + options: Models.ServiceSetPropertiesOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async getProperties( + options: Models.ServiceGetPropertiesOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async getStatistics( + options: Models.ServiceGetStatisticsOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } +} diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts new file mode 100644 index 000000000..64dca9cab --- /dev/null +++ b/src/table/handlers/TableHandler.ts @@ -0,0 +1,185 @@ +import * as Models from "../generated/artifacts/models"; +import Context from "../generated/Context"; +import BaseHandler from "./BaseHandler"; + +import TableStorageContext from "../context/TableStorageContext"; +import NotImplementedError from "../errors/NotImplementedError"; +import StorageErrorFactory from "../errors/StorageErrorFactory"; +import ITableHandler from "../generated/handlers/ITableHandler"; +import { TableModel } from "../persistence/ITableMetadataStore"; + +import { + DEFAULT_TABLE_LISTENING_PORT, + DEFAULT_TABLE_SERVER_HOST_NAME, + FULL_METADATA_ACCEPT, + MINIMAL_METADATA_ACCEPT, + NO_METADATA_ACCEPT, + TABLE_API_VERSION +} from "../utils/constants"; + +export default class TableHandler extends BaseHandler implements ITableHandler { + public async create( + tableProperties: Models.TableProperties, + options: Models.TableCreateOptionalParams, + context: Context + ): Promise { + const tableCtx = new TableStorageContext(context); + const accountName = tableCtx.account; + + if (accountName === undefined) { + throw StorageErrorFactory.getAccountNameEmpty(); + } + + const tableName = tableCtx.tableName; + if (tableName === undefined) { + throw StorageErrorFactory.getTableNameEmpty(); + } + + const metadata = `${accountName}/$metadata#Tables/@Element`; + const type = `${accountName}.Tables`; + const id = `Tables(${tableName})`; + const editLink = `Tables(${tableName})`; + + const table: TableModel = { + account: accountName, + name: tableName, + odatametadata: metadata, + odatatype: type, + odataid: id, + odataeditLink: editLink + }; + + const statusCode = await this.metadataStore.createTable(context, table); + const response: Models.TableCreateResponse = { + clientRequestId: options.requestId, + requestId: tableCtx.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode + }; + + let protocol = "http"; + let host = + DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; + if (tableCtx.request !== undefined) { + host = tableCtx.request.getHeader("host") as string; + protocol = tableCtx.request.getProtocol() as string; + } + + if (tableCtx.accept === NO_METADATA_ACCEPT) { + response.tableName = tableName; + } + + if (tableCtx.accept === MINIMAL_METADATA_ACCEPT) { + response.tableName = tableName; + response.odatametadata = `${protocol}://${host}/${metadata}`; + } + + if (tableCtx.accept === FULL_METADATA_ACCEPT) { + response.tableName = tableName; + response.odatametadata = `${protocol}://${host}/${metadata}`; + response.odatatype = type; + response.odataid = `${protocol}://${host}/${id}`; + response.odataeditLink = editLink; + } + return response; + } + + public async query( + options: Models.TableQueryOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async delete( + table: string, + options: Models.TableDeleteMethodOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async queryEntities( + table: string, + options: Models.TableQueryEntitiesOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async queryEntitiesWithPartitionAndRowKey( + table: string, + partitionKey: string, + rowKey: string, + options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async updateEntity( + table: string, + partitionKey: string, + rowKey: string, + options: Models.TableUpdateEntityOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async mergeEntity( + table: string, + partitionKey: string, + rowKey: string, + options: Models.TableMergeEntityOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async deleteEntity( + table: string, + partitionKey: string, + rowKey: string, + ifMatch: string, + options: Models.TableDeleteEntityOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async insertEntity( + table: string, + options: Models.TableInsertEntityOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async getAccessPolicy( + table: string, + options: Models.TableGetAccessPolicyOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async setAccessPolicy( + table: string, + options: Models.TableSetAccessPolicyOptionalParams, + context: Context + ): Promise { + // TODO + throw new NotImplementedError(); + } +} diff --git a/src/table/main.ts b/src/table/main.ts new file mode 100644 index 000000000..348d2fe62 --- /dev/null +++ b/src/table/main.ts @@ -0,0 +1,85 @@ +#!/usr/bin/env node +import { access } from "fs"; +import { dirname, join } from "path"; +import { promisify } from "util"; + +import * as Logger from "../common/Logger"; +import TableConfiguration from "./TableConfiguration"; +import TableEnvironment from "./TableEnvironment"; +import TableServer from "./TableServer"; +import { DEFAULT_TABLE_LOKI_DB_PATH } from "./utils/constants"; + +// tslint:disable:no-console + +/** + * Entry for Azurite table service + */ +async function main() { + // Initialize the environment from the command line parameters + const env = new TableEnvironment(); + + // Check access for process location + const accessAsync = promisify(access); + const location = await env.location(); + await accessAsync(location); + + // Check access for debug file path + const debugFilePath = await env.debug(); + if (debugFilePath !== undefined) { + await accessAsync(dirname(debugFilePath)); + } + + // Store table configuation + const config = new TableConfiguration( + env.tableHost(), + env.tablePort(), + join(location, DEFAULT_TABLE_LOKI_DB_PATH), + !env.silent(), + undefined, + (await env.debug()) !== undefined, + await env.debug(), + env.loose(), + env.skipApiVersionCheck() + ); + + // We use logger singleton as global debugger logger to track detailed outputs cross layers + // Note that, debug log is different from access log which is only available in request handler layer to + // track every request. Access log is not singleton, and initialized in specific RequestHandlerFactory implementations + // Enable debug log by default before first release for debugging purpose + Logger.configLogger(config.enableDebugLog, config.debugLogFilePath); + + // Create server instance + const server = new TableServer(config); + + const beforeStartMessage = `Azurite Table service is starting on ${config.host}:${config.port}`; + const afterStartMessage = `Azurite Table service successfully started on ${config.host}:${config.port}`; + const beforeCloseMessage = `Azurite Table service is closing...`; + const afterCloseMessage = `Azurite Table service successfully closed`; + + // Start Server + console.log(beforeStartMessage); + await server.start(); + console.log(afterStartMessage); + + // Handle close event + process + .once("message", msg => { + if (msg === "shutdown") { + console.log(beforeCloseMessage); + server.close().then(() => { + console.log(afterCloseMessage); + }); + } + }) + .once("SIGINT", () => { + console.log(beforeCloseMessage); + server.clean().then(() => { + console.log(afterCloseMessage); + }); + }); +} + +main().catch(err => { + console.error(`Exit die to unhandled error: ${err.message}`); + process.exit(1); +}); diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts new file mode 100644 index 000000000..8f15ef657 --- /dev/null +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -0,0 +1,109 @@ +import { NextFunction, Request, RequestHandler, Response } from "express"; +import uuid from "uuid/v4"; + +import logger from "../../common/Logger"; +import { PRODUCTION_STYLE_URL_HOSTNAME } from "../../common/utils/constants"; +import TableStorageContext from "../context/TableStorageContext"; +import { + DEFAULT_TABLE_CONTEXT_PATH, + HeaderConstants +} from "../utils/constants"; + +export default function createTableStorageContextMiddleware(): RequestHandler { + return (req: Request, res: Response, next: NextFunction) => { + return tableStorageContextMiddleware(req, res, next); + }; +} + +/** + * A middleware extract related table service context. + * + * @export + * @param {Request} req An express compatible Request object + * @param {Response} res An express compatible Response object + * @param {NextFunction} next An express middleware next callback + */ +export function tableStorageContextMiddleware( + req: Request, + res: Response, + next: NextFunction +): void { + // Set server header in every Azurite response + res.setHeader( + HeaderConstants.SERVER, + `Azurite-table/${HeaderConstants.VERSION}` + ); + + const requestID = uuid(); + + const tableContext = new TableStorageContext( + res.locals, + DEFAULT_TABLE_CONTEXT_PATH + ); + + tableContext.accept = req.headers.accept; + tableContext.startTime = new Date(); + tableContext.xMsRequestID = requestID; + + logger.info( + `TableStorageContextMiddleware: RequestMethod=${req.method} RequestURL=${ + req.protocol + }://${req.hostname}${req.url} RequestHeaders:${JSON.stringify( + req.headers + )} ClientIP=${req.ip} Protocol=${req.protocol} HTTPVersion=${ + req.httpVersion + }`, + requestID + ); + + const [account, table] = extractStoragePartsFromPath(req.hostname, req.path); + + tableContext.account = account; + tableContext.tableName = table; + + // Emulator's URL pattern is like http://hostname[:port]/account/table + // (or, alternatively, http[s]://account.localhost[:port]/table/) + // Create a router to exclude account name from req.path, as url path in swagger doesn't include account + // Exclude account name from req.path for dispatchMiddleware + tableContext.dispatchPattern = table !== undefined ? `/Tables` : "/"; + + logger.info( + `tableStorageContextMiddleware: Account=${account} tableName=${table}}`, + requestID + ); + next(); +} + +/** + * Extract storage account, table, and messages from URL path. + * + * @param {string} path + * @returns {([string | undefined, string | undefined, string | undefined, boolean | undefined])} + */ +export function extractStoragePartsFromPath( + hostname: string, + path: string +): [string | undefined, string | undefined] { + let account; + let table; + + const decodedPath = decodeURIComponent(path); + const normalizedPath = decodedPath.startsWith("/") + ? decodedPath.substr(1) + : decodedPath; // Remove starting "/" + + const parts = normalizedPath.split("/"); + + let urlPartIndex = 0; + if (hostname.endsWith(PRODUCTION_STYLE_URL_HOSTNAME)) { + account = hostname.substring( + 0, + hostname.length - PRODUCTION_STYLE_URL_HOSTNAME.length + ); + } else { + account = parts[urlPartIndex++]; + } + table = parts[urlPartIndex++]; + + return [account, table]; +} diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts new file mode 100644 index 000000000..675890cad --- /dev/null +++ b/src/table/persistence/ITableMetadataStore.ts @@ -0,0 +1,64 @@ +import * as Models from "../generated/artifacts/models"; +import Context from "../generated/Context"; +import { TABLE_STATUSCODE } from "../utils/constants"; + +// Since the host name may change, we don't store host in {@code odatametadata, odatatid} +interface ITtableAdditionalProperties { + tableAcl?: Models.SignedIdentifier[]; + account: string; + name: string; + odatametadata?: string; + odatatype?: string; + odataid?: string; + odataeditLink?: string; +} + +export type TableModel = ITtableAdditionalProperties; + +export default interface ITableMetadataStore { + queryTable(context: Context): Promise; + createTable(context: Context, table: TableModel): Promise; + deleteTable(context: Context, tableName: string): Promise; + queryTableEntities( + context: Context, + table: string, + propertyName: Array + ): Promise<{ [propertyName: string]: any }[]>; + queryTableEntitiesWithPartitionAndRowKey( + context: Context, + table: string, + partitionKey: string, + rowKey: string + ): Promise<{ [propertyName: string]: any }[]>; + updateTableEntity( + context: Context, + table: string, + partitionKey: string, + rowKey: string + ): Promise; + mergeTableEntity( + context: Context, + table: string, + partitionKey: string, + rowKey: string + ): Promise; + deleteTableEntity( + context: Context, + table: string, + partitionKey: string, + rowKey: string + ): Promise; + insertTableEntity(context: Context, table: string): Promise; + getTableAccessPolicy( + context: Context, + table: string, + options: Models.TableGetAccessPolicyOptionalParams + ): Promise; + setTableAccessPolicy( + context: Context, + table: string, + options: Models.TableSetAccessPolicyOptionalParams + ): Promise; + init(): void; + close(): void; +} diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts new file mode 100644 index 000000000..1af8c8288 --- /dev/null +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -0,0 +1,188 @@ +import { stat } from "fs"; +import Loki from "lokijs"; + +import NotImplementedError from "../errors/NotImplementedError"; +import StorageErrorFactory from "../errors/StorageErrorFactory"; +import * as Models from "../generated/artifacts/models"; +import Context from "../generated/Context"; +import { TableModel } from "../persistence/ITableMetadataStore"; +import { TABLE_STATUSCODE } from "../utils/constants"; +import ITableMetadataStore from "./ITableMetadataStore"; + +export default class LokiTableMetadataStore implements ITableMetadataStore { + private readonly db: Loki; + private readonly TABLE_COLLECTION = "$TABLE_COLLECTION$"; + private initialized: boolean = false; + private closed: boolean = false; + + public constructor(public readonly lokiDBPath: string) { + this.db = new Loki(lokiDBPath, { + autosave: true, + autosaveInterval: 5000 + }); + } + + public isInitialized(): boolean { + return this.initialized; + } + + public isClosed(): boolean { + return this.closed; + } + + public async createTable( + context: Context, + table: TableModel + ): Promise { + const coll = this.db.getCollection(this.TABLE_COLLECTION); + const doc = coll.findOne({ + accountName: table.account, + name: table.name + }); + + // If the metadata exists, we will throw getTableAlreadyExists error + if (doc) { + throw StorageErrorFactory.getTableAlreadyExists( + context.contextID + ); + } + + coll.insert(table); + return 201; + } + + public async queryTable(context: Context): Promise { + // TODO + throw new NotImplementedError(); + } + + public async deleteTable(context: Context, tableName: string): Promise { + // TODO context: Context + throw new NotImplementedError(); + } + + public async queryTableEntities( + context: Context, + table: string, + propertyName: Array + ): Promise<{ [propertyName: string]: any }[]> { + // TODO + throw new NotImplementedError(); + } + + public async queryTableEntitiesWithPartitionAndRowKey( + context: Context, + table: string, + partitionKey: string, + rowKey: string + ): Promise<{ [propertyName: string]: any }[]> { + // TODO + throw new NotImplementedError(); + } + + public async updateTableEntity( + context: Context, + table: string, + partitionKey: string, + rowKey: string + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async mergeTableEntity( + context: Context, + table: string, + partitionKey: string, + rowKey: string + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async deleteTableEntity( + context: Context, + table: string, + partitionKey: string, + rowKey: string + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async insertTableEntity(context: Context, table: string): Promise { + // TODO + throw new NotImplementedError(); + } + + public async getTableAccessPolicy( + context: Context, + table: string + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async setTableAccessPolicy( + context: Context, + table: string + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async init(): Promise { + await new Promise((resolve, reject) => { + stat(this.lokiDBPath, (statError, stats) => { + if (!statError) { + this.db.loadDatabase({}, dbError => { + if (dbError) { + reject(dbError); + } else { + resolve(); + } + }); + } else { + // when DB file doesn't exist, ignore the error because following will re-create the file + resolve(); + } + }); + }); + + // Create tables collection if not exists + if (this.db.getCollection(this.TABLE_COLLECTION) === null) { + this.db.addCollection(this.TABLE_COLLECTION, { + // Optimization for indexing and searching + // https://rawgit.com/techfort/LokiJS/master/jsdoc/tutorial-Indexing%20and%20Query%20performance.html + indices: ["accountName", "name"] + }); // Optimize for find operation + } + + await new Promise((resolve, reject) => { + this.db.saveDatabase(err => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + + this.initialized = true; + this.closed = false; + } + + public async close(): Promise { + await new Promise((resolve, reject) => { + this.db.close(err => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + + this.closed = true; + } +} diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts new file mode 100644 index 000000000..51d83d6a9 --- /dev/null +++ b/src/table/utils/constants.ts @@ -0,0 +1,25 @@ +export const DEFAULT_TABLE_EXTENT_LOKI_DB_PATH = + "__azurite_db_table_extent__.json"; +export const DEFAULT_TABLE_LOKI_DB_PATH = "__azurite_db_table__.json"; + +export const DEFAULT_TABLE_SERVER_HOST_NAME = "127.0.0.1"; // Change to 0.0.0.0 when needs external access +export const DEFAULT_TABLE_LISTENING_PORT = 10002; +export const DEFAULT_ENABLE_ACCESS_LOG = true; +export const DEFAULT_ENABLE_DEBUG_LOG = true; + +export enum TABLE_STATUSCODE { + CREATED = 201, + NOCONTENT = 204 +} + +export const DEFAULT_TABLE_CONTEXT_PATH = "azurite_table_context"; +export const TABLE_API_VERSION = "2019-12-12"; + +export const HeaderConstants = { + SERVER: "Server", + VERSION: "3.8.0" +}; + +export const NO_METADATA_ACCEPT = "application/json;odata=nometadata"; +export const MINIMAL_METADATA_ACCEPT = "application/json;odata=minimalmetadata"; +export const FULL_METADATA_ACCEPT = "application/json;odata=fullmetadata"; diff --git a/swagger/table.md b/swagger/table.md new file mode 100644 index 000000000..dc84619c1 --- /dev/null +++ b/swagger/table.md @@ -0,0 +1,69 @@ +# Azurite Server Table + +> see https://aka.ms/autorest + +```yaml +package-name: azurite-server-table +title: AzuriteServerTable +description: Azurite Server for Table +enable-xml: true +generate-metadata: false +license-header: MICROSOFT_MIT_NO_VERSION +output-folder: ../src/table/generated +input-file: ./table/table.json +model-date-time-as-string: true +optional-response-headers: true +enum-types: true +``` + +### ApiVersionParameter -> Update to optional + +```yaml +directive: + - from: swagger-document + where: $.parameters.ApiVersionParameter + transform: > + $["required"]= false; +``` + +### DataServiceVersionParameter -> Update to optional + +```yaml +directive: + - from: swagger-document + where: $.parameters.DataServiceVersionParameter + transform: > + $["required"]= false; +``` + +### Create Table -> Update response + +```yaml +directive: + - from: swagger-document + where: $.definitions + transform: > + $["TableResponse"]["properties"] = { + "odata.metadata": { + "description": "The metadata response of the table.", + "type": "string" + }, + "TableName": { + "description": "The name of the table.", + "type": "string" + }, + "odata.type": { + "description": "The odata type of the table.", + "type": "string" + }, + "odata.id": { + "description": "The id of the table.", + "type": "string" + }, + "odata.editLink": { + "description": "The edit link of the table.", + "type": "string" + } + }; + $["TableResponse"]["allOf"] = undefined; +``` diff --git a/swagger/table/examples/TableCreate.json b/swagger/table/examples/TableCreate.json new file mode 100644 index 000000000..803e06fd5 --- /dev/null +++ b/swagger/table/examples/TableCreate.json @@ -0,0 +1,22 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "DataServiceVersion": "3.0", + "url": "myaccount.table.core.windows.net", + "tableProperties": { + "TableName": "mytable" + } + }, + "responses": { + "201": { + "body": { + "odata.metadata": "https://myaccount.table.core.windows.net/$metadata#Tables/@Element", + "odata.type": " myaccount.Tables", + "odata.id": "https://myaccount.table.core.windows.net/Tables('mytable')", + "odata.editLink": "Tables('mytable')", + "TableName": "mytable" + } + }, + "204": {} + } +} diff --git a/swagger/table/examples/TableDelete.json b/swagger/table/examples/TableDelete.json new file mode 100644 index 000000000..0cc1f4bb0 --- /dev/null +++ b/swagger/table/examples/TableDelete.json @@ -0,0 +1,10 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "url": "myaccount.table.core.windows.net", + "table": "mytable" + }, + "responses": { + "204": {} + } +} diff --git a/swagger/table/examples/TableDeleteEntity.json b/swagger/table/examples/TableDeleteEntity.json new file mode 100644 index 000000000..2d0f7a9a5 --- /dev/null +++ b/swagger/table/examples/TableDeleteEntity.json @@ -0,0 +1,14 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "DataServiceVersion": "3.0", + "If-Match": "*", + "url": "myaccount.table.core.windows.net", + "table": "Customers", + "partitionKey": "mypartitionkey", + "rowKey": "myrowkey" + }, + "responses": { + "204": {} + } +} diff --git a/swagger/table/examples/TableGet.json b/swagger/table/examples/TableGet.json new file mode 100644 index 000000000..018859152 --- /dev/null +++ b/swagger/table/examples/TableGet.json @@ -0,0 +1,23 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "DataServiceVersion": "3.0", + "$top": 1, + "url": "myaccount.table.core.windows.net" + }, + "responses": { + "200": { + "body": { + "odata.metadata": "https://myaccount.table.core.windows.net/$metadata#Tables", + "value": [ + { + "odata.type": "myaccount.Tables", + "odata.id": "https://myaccount.table.core.windows.net/Tables('mytable')", + "odata.editLink": "Tables('mytable')", + "TableName": "mytable" + } + ] + } + } + } +} diff --git a/swagger/table/examples/TableInsertEntity.json b/swagger/table/examples/TableInsertEntity.json new file mode 100644 index 000000000..749a5ac0a --- /dev/null +++ b/swagger/table/examples/TableInsertEntity.json @@ -0,0 +1,48 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "DataServiceVersion": "3.0", + "table": "Customer", + "url": "myaccount.table.core.windows.net", + "tableEntityProperties": { + "Address": "Mountain View", + "Age": 23, + "AmountDue": 200.23, + "CustomerCode@odata.type": "Edm.Guid", + "CustomerCode": "c9da6455-213d-42c9-9a79-3e9149a57833", + "CustomerSince@odata.type": "Edm.DateTime", + "CustomerSince": "2008-07-10T00:00:00", + "IsActive": true, + "NumberOfOrders@odata.type": "Edm.Int64", + "NumberOfOrders": "255", + "PartitionKey": "mypartitionkey", + "RowKey": "myrowkey" + } + }, + "responses": { + "201": { + "body": { + "odata.metadata": "https://myaccount.table.core.windows.net/Customer/$metadata#Customers/@Element", + "odata.type": "myaccount.Customers", + "odata.id": " https://myaccount.table.core.windows.net/Customers(PartitionKey='mypartitionkey',RowKey='myrowkey')", + "odata.etag": "W/\"0x5B168C7B6E589D2\"", + "odata.editLink": "Customers(PartitionKey='mypartitionkey',RowKey='myrowkey')", + "PartitionKey": "mypartitionkey", + "RowKey": "myrowkey", + "Timestamp@odata.type": "Edm.DateTime", + "Timestamp": "2013-08-22T01:12:06.2608595Z", + "Address": "Mountain View", + "Age": 23, + "AmountDue": 200.23, + "CustomerCode@odata.type": "Edm.Guid", + "CustomerCode": "c9da6455-213d-42c9-9a79-3e9149a57833", + "CustomerSince@odata.type": "Edm.DateTime", + "CustomerSince": "2008-07-10T00:00:00", + "IsActive": true, + "NumberOfOrders@odata.type": "Edm.Int64", + "NumberOfOrders": "255" + } + }, + "204": {} + } +} diff --git a/swagger/table/examples/TableMergeEntity.json b/swagger/table/examples/TableMergeEntity.json new file mode 100644 index 000000000..24e71afe7 --- /dev/null +++ b/swagger/table/examples/TableMergeEntity.json @@ -0,0 +1,27 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "DataServiceVersion": "3.0", + "url": "myaccount.table.core.windows.net", + "table": "Customers", + "partitionKey": "mypartitionkey", + "rowKey": "myrowkey", + "tableEntityProperties": { + "Address": "Santa Clara", + "Age": 23, + "AmountDue": 200.23, + "CustomerCode@odata.type": "Edm.Guid", + "CustomerCode": "c9da6455-213d-42c9-9a79-3e9149a57833", + "CustomerSince@odata.type": "Edm.DateTime", + "CustomerSince": "2008-07-10T00:00:00", + "IsActive": false, + "NumberOfOrders@odata.type": "Edm.Int64", + "NumberOfOrders": "255", + "PartitionKey": "mypartitionkey", + "RowKey": "myrowkey" + } + }, + "responses": { + "204": {} + } +} diff --git a/swagger/table/examples/TableQueryEntities.json b/swagger/table/examples/TableQueryEntities.json new file mode 100644 index 000000000..2daab5a9f --- /dev/null +++ b/swagger/table/examples/TableQueryEntities.json @@ -0,0 +1,30 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "DataServiceVersion": "3.0", + "url": "myaccount.table.core.windows.net", + "$top": 1, + "table": "Customer" + }, + "responses": { + "200": { + "body": { + "odata.metadata": " https://myaccount.table.core.windows.net/metadata#Customers", + "value": [ + { + "PartitionKey": "Customer", + "RowKey": "Name", + "odata.type": "myaccount.Customers", + "odata.id": "https://myaccount.table.core.windows.net/Customers(PartitionKey=Customer',RowKey='Name')", + "odata.etag": "W/\"0x5B168C7B6E589D2\"", + "odata.editLink": "Customers(PartitionKey=Customer',RowKey='Name')", + "Timestamp@odata.type": "Edm.DateTime", + "Timestamp": "2013-08-22T00:20:16.3134645Z", + "CustomerSince@odata.type": "Edm.DateTime", + "CustomerSince": "2008-10-01T15:25:05.2852025Z" + } + ] + } + } + } +} diff --git a/swagger/table/examples/TableQueryEntitiesWithPartitionAndRowKey.json b/swagger/table/examples/TableQueryEntitiesWithPartitionAndRowKey.json new file mode 100644 index 000000000..94896182a --- /dev/null +++ b/swagger/table/examples/TableQueryEntitiesWithPartitionAndRowKey.json @@ -0,0 +1,31 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "DataServiceVersion": "3.0", + "url": "myaccount.table.core.windows.net", + "table": "Customers", + "partitionKey": "Customer", + "rowKey": "Name" + }, + "responses": { + "200": { + "body": { + "odata.metadata": " https://myaccount.table.core.windows.net/metadata#Customers", + "value": [ + { + "odata.type": "myaccount.Customers", + "odata.id": "https://myaccount.table.core.windows.net/Customers(PartitionKey=Customer',RowKey='Name')", + "odata.etag": "W/\"0x5B168C7B6E589D2\"", + "odata.editLink": "Customers(PartitionKey=Customer',RowKey='Name')", + "PartitionKey": "Customer", + "RowKey": "Name", + "Timestamp@odata.type": "Edm.DateTime", + "Timestamp": "2013-08-22T00:20:16.3134645Z", + "CustomerSince@odata.type": "Edm.DateTime", + "CustomerSince": "2008-10-01T15:25:05.2852025Z" + } + ] + } + } + } +} diff --git a/swagger/table/examples/TableUpdateEntity.json b/swagger/table/examples/TableUpdateEntity.json new file mode 100644 index 000000000..24e71afe7 --- /dev/null +++ b/swagger/table/examples/TableUpdateEntity.json @@ -0,0 +1,27 @@ +{ + "parameters": { + "x-ms-version": "2019-02-02", + "DataServiceVersion": "3.0", + "url": "myaccount.table.core.windows.net", + "table": "Customers", + "partitionKey": "mypartitionkey", + "rowKey": "myrowkey", + "tableEntityProperties": { + "Address": "Santa Clara", + "Age": 23, + "AmountDue": 200.23, + "CustomerCode@odata.type": "Edm.Guid", + "CustomerCode": "c9da6455-213d-42c9-9a79-3e9149a57833", + "CustomerSince@odata.type": "Edm.DateTime", + "CustomerSince": "2008-07-10T00:00:00", + "IsActive": false, + "NumberOfOrders@odata.type": "Edm.Int64", + "NumberOfOrders": "255", + "PartitionKey": "mypartitionkey", + "RowKey": "myrowkey" + } + }, + "responses": { + "204": {} + } +} diff --git a/swagger/table/table.json b/swagger/table/table.json new file mode 100644 index 000000000..abc01960c --- /dev/null +++ b/swagger/table/table.json @@ -0,0 +1,1913 @@ +{ + "swagger": "2.0", + "info": { + "title": "Azure Table", + "version": "2019-02-02", + "x-ms-code-generation-settings": { + "header": "MIT", + "strictSpecAdherence": false + } + }, + "x-ms-parameterized-host": { + "hostTemplate": "{url}", + "useSchemePrefix": false, + "positionInOperation": "first", + "parameters": [ + { + "$ref": "#/parameters/Url" + } + ] + }, + "securityDefinitions": { + "table_shared_key": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, + "schemes": [ + "https" + ], + "consumes": [ + "application/json;odata=nometadata" + ], + "produces": [ + "application/json;odata=minimalmetadata" + ], + "paths": { + "/Tables": { + "get": { + "tags": [ + "table" + ], + "operationId": "Table_Query", + "x-ms-examples": { + "TableGet": { + "$ref": "./examples/TableGet.json" + } + }, + "description": "Queries tables under the given account.", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/formatParameter" + }, + { + "$ref": "#/parameters/topParameter" + }, + { + "$ref": "#/parameters/selectParameter" + }, + { + "$ref": "#/parameters/filterParameter" + }, + { + "name": "NextTableName", + "in": "query", + "required": false, + "type": "string", + "description": "A table query continuation token from a previous call." + } + ], + "responses": { + "200": { + "description": "Success, table query completed.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-continuation-NextTableName": { + "type": "string", + "description": "This header contains the continuation token value." + } + }, + "schema": { + "$ref": "#/definitions/TableQueryResponse" + } + } + } + }, + "post": { + "tags": [ + "table" + ], + "operationId": "Table_Create", + "x-ms-examples": { + "TableCreate": { + "$ref": "./examples/TableCreate.json" + } + }, + "description": "Creates a new table under the given account.", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/formatParameter" + }, + { + "$ref": "#/parameters/TableProperties" + }, + { + "$ref": "#/parameters/PreferParameter" + } + ], + "responses": { + "201": { + "description": "Success, table created.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "Preference-Applied": { + "type": "string", + "description": "Indicates whether the Prefer request header was honored. If the response does not include this header, then the Prefer header was not honored. If this header is returned, its value will either be return-content or return-no-content." + } + }, + "schema": { + "$ref": "#/definitions/TableResponse" + } + }, + "204": { + "description": "Success, table created.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "Preference-Applied": { + "type": "string", + "description": "Indicates whether the Prefer request header was honored. If the response does not include this header, then the Prefer header was not honored. If this header is returned, its value will either be return-content or return-no-content." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + } + }, + "/Tables('{table}')": { + "delete": { + "tags": [ + "table" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "operationId": "Table_Delete", + "x-ms-examples": { + "TableDelete": { + "$ref": "./examples/TableDelete.json" + } + }, + "description": "Operation permanently deletes the specified table.", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/tableNameParameter" + } + ], + "responses": { + "204": { + "description": "No Content", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + } + }, + "/{table}()": { + "get": { + "tags": [ + "table" + ], + "operationId": "Table_QueryEntities", + "x-ms-examples": { + "TableQueryEntities": { + "$ref": "./examples/TableQueryEntities.json" + } + }, + "description": "Queries entities in a table.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/formatParameter" + }, + { + "$ref": "#/parameters/topParameter" + }, + { + "$ref": "#/parameters/selectParameter" + }, + { + "$ref": "#/parameters/filterParameter" + }, + { + "$ref": "#/parameters/tableNameParameter" + }, + { + "name": "NextPartitionKey", + "in": "query", + "required": false, + "type": "string", + "description": "An entity query continuation token from a previous call." + }, + { + "name": "NextRowKey", + "in": "query", + "required": false, + "type": "string", + "description": "An entity query continuation token from a previous call." + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "x-ms-continuation-NextPartitionKey": { + "type": "string", + "description": "This header contains the continuation token value for partition key." + }, + "x-ms-continuation-NextRowKey": { + "type": "string", + "description": "This header contains the continuation token value for row key." + } + }, + "schema": { + "$ref": "#/definitions/TableEntityQueryResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + } + }, + "/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')": { + "get": { + "tags": [ + "table" + ], + "operationId": "Table_QueryEntitiesWithPartitionAndRowKey", + "x-ms-examples": { + "TableQueryEntitiesWithPartitionAndRowKey": { + "$ref": "./examples/TableQueryEntitiesWithPartitionAndRowKey.json" + } + }, + "description": "Queries entities in a table.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/formatParameter" + }, + { + "$ref": "#/parameters/selectParameter" + }, + { + "$ref": "#/parameters/filterParameter" + }, + { + "$ref": "#/parameters/tableNameParameter" + }, + { + "$ref": "#/parameters/partitionKeyParameter" + }, + { + "$ref": "#/parameters/rowKeyParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "ETag": { + "type": "string", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated" + }, + "x-ms-continuation-NextPartitionKey": { + "type": "string", + "description": "This header contains the continuation token value for partition key." + }, + "x-ms-continuation-NextRowKey": { + "type": "string", + "description": "This header contains the continuation token value for row key." + } + }, + "schema": { + "$ref": "#/definitions/TableEntityQueryResponse" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + }, + "put": { + "tags": [ + "table" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "operationId": "Table_UpdateEntity", + "x-ms-examples": { + "TableUpdateEntity": { + "$ref": "./examples/TableUpdateEntity.json" + } + }, + "description": "Update entity in a table.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/formatParameter" + }, + { + "$ref": "#/parameters/TableEntityProperties" + }, + { + "$ref": "#/parameters/tableNameParameter" + }, + { + "$ref": "#/parameters/partitionKeyParameter" + }, + { + "$ref": "#/parameters/rowKeyParameter" + }, + { + "name": "If-Match", + "in": "header", + "required": false, + "type": "string", + "description": "Match condition for an entity to be updated. If specified and a matching entity is not found, an error will be raised. To force an unconditional update, set to the wildcard character (*). If not specified, an insert will be performed when no existing entity is found to update and a replace will be performed if an existing entity is found.", + "x-ms-client-name": "IfMatch" + } + ], + "responses": { + "204": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "ETag": { + "type": "string", + "description": "UTC date/time value generated by the service that indicates the time at which the entity was last updated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + }, + "patch": { + "tags": [ + "table" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "operationId": "Table_MergeEntity", + "x-ms-examples": { + "TableMergeEntity": { + "$ref": "./examples/TableMergeEntity.json" + } + }, + "description": "Merge entity in a table.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/formatParameter" + }, + { + "$ref": "#/parameters/TableEntityProperties" + }, + { + "$ref": "#/parameters/tableNameParameter" + }, + { + "$ref": "#/parameters/partitionKeyParameter" + }, + { + "$ref": "#/parameters/rowKeyParameter" + }, + { + "name": "If-Match", + "in": "header", + "required": false, + "type": "string", + "description": "Match condition for an entity to be updated. If specified and a matching entity is not found, an error will be raised. To force an unconditional update, set to the wildcard character (*). If not specified, an insert will be performed when no existing entity is found to update and a merge will be performed if an existing entity is found.", + "x-ms-client-name": "IfMatch" + } + ], + "responses": { + "204": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "ETag": { + "type": "string", + "description": "UTC date/time value generated by the service that indicates the time at which the entity was last updated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + }, + "delete": { + "tags": [ + "table" + ], + "operationId": "Table_DeleteEntity", + "x-ms-examples": { + "TableDeleteEntity": { + "$ref": "./examples/TableDeleteEntity.json" + } + }, + "description": "Deletes the specified entity in a table.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/formatParameter" + }, + { + "$ref": "#/parameters/tableNameParameter" + }, + { + "$ref": "#/parameters/partitionKeyParameter" + }, + { + "$ref": "#/parameters/rowKeyParameter" + }, + { + "name": "If-Match", + "in": "header", + "required": true, + "type": "string", + "description": "Match condition for an entity to be deleted. If specified and a matching entity is not found, an error will be raised. To force an unconditional delete, set to the wildcard character (*).", + "x-ms-client-name": "IfMatch" + } + ], + "responses": { + "204": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + } + }, + "/{table}": { + "post": { + "tags": [ + "table" + ], + "operationId": "Table_InsertEntity", + "x-ms-examples": { + "TableInsertEntity": { + "$ref": "./examples/TableInsertEntity.json" + } + }, + "description": "Insert entity in a table.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/formatParameter" + }, + { + "$ref": "#/parameters/TableEntityProperties" + }, + { + "$ref": "#/parameters/tableNameParameter" + }, + { + "$ref": "#/parameters/PreferParameter" + } + ], + "responses": { + "201": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "ETag": { + "type": "string", + "description": "UTC date/time value generated by the service that indicates the time at which the entity was last updated." + }, + "Preference-Applied": { + "type": "string", + "description": "Indicates whether the Prefer request header was honored. If the response does not include this header, then the Prefer header was not honored. If this header is returned, its value will either be return-content or return-no-content." + }, + "Content-Type": { + "type": "string", + "description": "Indicates the content type of the payload. The value depends on the value specified for the Accept request header." + } + }, + "schema": { + "$ref": "#/definitions/TableEntityProperties" + } + }, + "204": { + "description": "No Content.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + }, + "ETag": { + "type": "string", + "description": "UTC date/time value generated by the service that indicates the time at which the entity was last updated." + }, + "Preference-Applied": { + "type": "string", + "description": "Indicates whether the Prefer request header was honored. If the response does not include this header, then the Prefer header was not honored. If this header is returned, its value will either be return-content or return-no-content." + }, + "Content-Type": { + "type": "string", + "description": "Indicates the content type of the payload. The value depends on the value specified for the Accept request header." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + }, + "get": { + "tags": [ + "table" + ], + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "operationId": "Table_GetAccessPolicy", + "description": "Retrieves details about any stored access policies specified on the table that may be used with Shared Access Signatures.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/tableNameParameter" + }, + { + "$ref": "#/parameters/compAclParameter" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "$ref": "#/definitions/SignedIdentifiers" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + }, + "put": { + "tags": [ + "table" + ], + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "operationId": "Table_SetAccessPolicy", + "description": "Sets stored access policies for the table that may be used with Shared Access Signatures.", + "parameters": [ + { + "$ref": "#/parameters/TableAcl" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/tableNameParameter" + }, + { + "$ref": "#/parameters/compAclParameter" + } + ], + "responses": { + "204": { + "description": "No Content", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + } + } + }, + "x-ms-paths": { + "/?ServiceProperties": { + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "service" + ], + "description": "Required query string to set the service properties." + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "properties" + ], + "description": "Required query string to set the service properties." + } + ], + "put": { + "tags": [ + "service" + ], + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "operationId": "Service_SetProperties", + "description": "Sets properties for an account's Table service endpoint, including properties for Analytics and CORS (Cross-Origin Resource Sharing) rules.", + "parameters": [ + { + "$ref": "#/parameters/TableServiceProperties" + }, + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "202": { + "description": "Success (Accepted)", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + } + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + }, + "get": { + "tags": [ + "service" + ], + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "operationId": "Service_GetProperties", + "description": "Gets the properties of an account's Table service, including properties for Analytics and CORS (Cross-Origin Resource Sharing) rules.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + } + }, + "schema": { + "$ref": "#/definitions/TableServiceProperties" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + } + }, + "/?ServiceStats": { + "parameters": [ + { + "name": "restype", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "service" + ], + "description": "Required query string to get service stats." + }, + { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "stats" + ], + "description": "Required query string to get service stats." + } + ], + "get": { + "tags": [ + "service" + ], + "consumes": [ + "application/xml" + ], + "produces": [ + "application/xml" + ], + "operationId": "Service_GetStatistics", + "description": "Retrieves statistics related to replication for the Table service. It is only available on the secondary location endpoint when read-access geo-redundant replication is enabled for the account.", + "parameters": [ + { + "$ref": "#/parameters/Timeout" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + } + ], + "responses": { + "200": { + "description": "Success.", + "headers": { + "x-ms-client-request-id": { + "x-ms-client-name": "ClientRequestId", + "type": "string", + "description": "If a client request id header is sent in the request, this header will be present in the response with the same value." + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Table service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "$ref": "#/definitions/TableServiceStats" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + } + } + }, + "definitions": { + "TableServiceError": { + "description": "Table Service error.", + "type": "object", + "xml": {}, + "properties": { + "Message": { + "description": "The error message.", + "type": "string", + "xml": { + "name": "Message" + } + } + } + }, + "TableServiceProperties": { + "description": "Table Service Properties.", + "type": "object", + "xml": { + "name": "StorageServiceProperties" + }, + "properties": { + "Logging": { + "description": "Azure Analytics Logging settings.", + "$ref": "#/definitions/Logging" + }, + "HourMetrics": { + "description": "A summary of request statistics grouped by API in hourly aggregates for tables.", + "$ref": "#/definitions/Metrics" + }, + "MinuteMetrics": { + "description": "A summary of request statistics grouped by API in minute aggregates for tables.", + "$ref": "#/definitions/Metrics" + }, + "Cors": { + "description": "The set of CORS rules.", + "type": "array", + "items": { + "$ref": "#/definitions/CorsRule" + }, + "xml": { + "wrapped": true, + "name": "Cors" + } + } + } + }, + "Logging": { + "xml": { + "name": "Logging" + }, + "description": "Azure Analytics Logging settings.", + "type": "object", + "required": [ + "Version", + "Delete", + "Read", + "Write", + "RetentionPolicy" + ], + "properties": { + "Version": { + "description": "The version of Analytics to configure.", + "type": "string", + "xml": { + "name": "Version" + } + }, + "Delete": { + "description": "Indicates whether all delete requests should be logged.", + "type": "boolean", + "xml": { + "name": "Delete" + } + }, + "Read": { + "description": "Indicates whether all read requests should be logged.", + "type": "boolean", + "xml": { + "name": "Read" + } + }, + "Write": { + "description": "Indicates whether all write requests should be logged.", + "type": "boolean", + "xml": { + "name": "Write" + } + }, + "RetentionPolicy": { + "$ref": "#/definitions/RetentionPolicy" + } + } + }, + "Metrics": { + "xml": {}, + "description": "", + "required": [ + "Enabled" + ], + "properties": { + "Version": { + "description": "The version of Analytics to configure.", + "type": "string", + "xml": { + "name": "Version" + } + }, + "Enabled": { + "description": "Indicates whether metrics are enabled for the Table service.", + "type": "boolean", + "xml": { + "name": "Enabled" + } + }, + "IncludeAPIs": { + "description": "Indicates whether metrics should generate summary statistics for called API operations.", + "type": "boolean", + "xml": { + "name": "IncludeAPIs" + } + }, + "RetentionPolicy": { + "$ref": "#/definitions/RetentionPolicy" + } + } + }, + "CorsRule": { + "xml": { + "name": "CorsRule" + }, + "description": "CORS is an HTTP feature that enables a web application running under one domain to access resources in another domain. Web browsers implement a security restriction known as same-origin policy that prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin domain) to call APIs in another domain.", + "type": "object", + "required": [ + "AllowedOrigins", + "AllowedMethods", + "AllowedHeaders", + "ExposedHeaders", + "MaxAgeInSeconds" + ], + "properties": { + "AllowedOrigins": { + "description": "The origin domains that are permitted to make a request against the service via CORS. The origin domain is the domain from which the request originates. Note that the origin must be an exact case-sensitive match with the origin that the user age sends to the service. You can also use the wildcard character '*' to allow all origin domains to make requests via CORS.", + "type": "string", + "xml": { + "name": "AllowedOrigins" + } + }, + "AllowedMethods": { + "description": "The methods (HTTP request verbs) that the origin domain may use for a CORS request. (comma separated)", + "type": "string", + "xml": { + "name": "AllowedMethods" + } + }, + "AllowedHeaders": { + "description": "The request headers that the origin domain may specify on the CORS request.", + "type": "string", + "xml": { + "name": "AllowedHeaders" + } + }, + "ExposedHeaders": { + "description": "The response headers that may be sent in the response to the CORS request and exposed by the browser to the request issuer.", + "type": "string", + "xml": { + "name": "ExposedHeaders" + } + }, + "MaxAgeInSeconds": { + "description": "The maximum amount time that a browser should cache the preflight OPTIONS request.", + "type": "integer", + "minimum": 0, + "xml": { + "name": "MaxAgeInSeconds" + } + } + } + }, + "RetentionPolicy": { + "xml": { + "name": "RetentionPolicy" + }, + "description": "The retention policy.", + "type": "object", + "required": [ + "Enabled" + ], + "properties": { + "Enabled": { + "description": "Indicates whether a retention policy is enabled for the service.", + "type": "boolean", + "xml": { + "name": "Enabled" + } + }, + "Days": { + "description": "Indicates the number of days that metrics or logging or soft-deleted data should be retained. All data older than this value will be deleted.", + "type": "integer", + "minimum": 1, + "xml": { + "name": "Days" + } + } + } + }, + "TableServiceStats": { + "description": "Stats for the service.", + "type": "object", + "xml": { + "name": "StorageServiceStats" + }, + "properties": { + "GeoReplication": { + "description": "Geo-Replication information for the Secondary Storage Service.", + "$ref": "#/definitions/GeoReplication" + } + } + }, + "GeoReplication": { + "xml": { + "name": "GeoReplication" + }, + "type": "object", + "required": [ + "Status", + "LastSyncTime" + ], + "properties": { + "Status": { + "description": "The status of the secondary location.", + "type": "string", + "enum": [ + "live", + "bootstrap", + "unavailable" + ], + "x-ms-enum": { + "name": "GeoReplicationStatusType", + "modelAsString": true + }, + "xml": { + "name": "Status" + } + }, + "LastSyncTime": { + "description": "A GMT date/time value, to the second. All primary writes preceding this value are guaranteed to be available for read operations at the secondary. Primary writes after this point in time may or may not be available for reads.", + "type": "string", + "format": "date-time-rfc1123", + "xml": { + "name": "LastSyncTime" + } + } + } + }, + "TableProperties": { + "description": "The properties for creating a table.", + "type": "object", + "properties": { + "TableName": { + "description": "The name of the table to create.", + "type": "string" + } + } + }, + "TableResponse": { + "description": "The response for a single table.", + "type": "object", + "properties": { + "odata.metadata": { + "description": "The metadata response of the table.", + "type": "string" + } + }, + "allOf": [ + { + "$ref": "#/definitions/TableResponseProperties" + } + ] + }, + "TableQueryResponse": { + "description": "The properties for the table query response.", + "type": "object", + "properties": { + "odata.metadata": { + "description": "The metadata response of the table.", + "type": "string" + }, + "value": { + "description": "List of tables.", + "type": "array", + "items": { + "$ref": "#/definitions/TableResponseProperties" + } + } + } + }, + "TableResponseProperties": { + "description": "The properties for the table response.", + "type": "object", + "properties": { + "TableName": { + "description": "The name of the table.", + "type": "string" + }, + "odata.type": { + "description": "The odata type of the table.", + "type": "string" + }, + "odata.id": { + "description": "The id of the table.", + "type": "string" + }, + "odata.editLink": { + "description": "The edit link of the table.", + "type": "string" + } + } + }, + "SignedIdentifier": { + "xml": { + "name": "SignedIdentifier" + }, + "description": "A signed identifier.", + "type": "object", + "required": [ + "Id", + "AccessPolicy" + ], + "properties": { + "Id": { + "type": "string", + "description": "A unique id.", + "xml": { + "name": "Id" + } + }, + "AccessPolicy": { + "description": "The access policy.", + "$ref": "#/definitions/AccessPolicy" + } + } + }, + "SignedIdentifiers": { + "description": "A collection of signed identifiers.", + "type": "array", + "items": { + "$ref": "#/definitions/SignedIdentifier", + "xml": { + "name": "SignedIdentifier" + } + }, + "xml": { + "wrapped": true, + "name": "SignedIdentifiers" + } + }, + "AccessPolicy": { + "xml": { + "name": "AccessPolicy" + }, + "type": "object", + "required": [ + "Start", + "Expiry", + "Permission" + ], + "description": "An Access policy.", + "properties": { + "Start": { + "description": "The start datetime from which the policy is active.", + "type": "string", + "format": "date-time", + "xml": { + "name": "Start" + } + }, + "Expiry": { + "description": "The datetime that the policy expires.", + "type": "string", + "format": "date-time", + "xml": { + "name": "Expiry" + } + }, + "Permission": { + "description": "The permissions for the acl policy.", + "type": "string", + "xml": { + "name": "Permission" + } + } + } + }, + "TableEntityQueryResponse": { + "description": "The properties for the table entity query response.", + "type": "object", + "properties": { + "odata.metadata": { + "description": "The metadata response of the table.", + "type": "string" + }, + "value": { + "description": "List of table entities.", + "type": "array", + "items": { + "$ref": "#/definitions/TableEntityProperties" + } + } + } + }, + "TableEntityProperties": { + "description": "The other properties of the table entity.", + "type": "object", + "additionalProperties": true + } + }, + "parameters": { + "Url": { + "name": "url", + "x-ms-parameter-location": "client", + "description": "The URL of the service account or table that is the targe of the desired operation.", + "required": true, + "type": "string", + "in": "path", + "x-ms-skip-url-encoding": true + }, + "TableServiceProperties": { + "name": "tableServiceProperties", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TableServiceProperties" + }, + "x-ms-parameter-location": "method", + "description": "The Table Service properties." + }, + "Timeout": { + "name": "timeout", + "in": "query", + "required": false, + "type": "integer", + "minimum": 0, + "x-ms-parameter-location": "method", + "description": "The timeout parameter is expressed in seconds." + }, + "ApiVersionParameter": { + "name": "x-ms-version", + "x-ms-parameter-location": "client", + "x-ms-client-name": "version", + "in": "header", + "required": true, + "type": "string", + "description": "Specifies the version of the operation to use for this request.", + "enum": [ + "2019-02-02" + ] + }, + "ClientRequestId": { + "name": "x-ms-client-request-id", + "x-ms-client-name": "requestId", + "in": "header", + "required": false, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when analytics logging is enabled." + }, + "DataServiceVersionParameter": { + "name": "DataServiceVersion", + "in": "header", + "required": true, + "type": "string", + "description": "Specifies the data service version.", + "x-ms-parameter-location": "method", + "enum": [ + "3.0" + ] + }, + "TableProperties": { + "name": "tableProperties", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TableProperties" + }, + "x-ms-parameter-location": "method", + "description": "The Table properties." + }, + "formatParameter": { + "name": "$format", + "in": "query", + "required": false, + "type": "string", + "description": "Specifies the media type for the response.", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "QueryOptions" + }, + "x-ms-client-name": "Format", + "enum": [ + "application/json;odata=nometadata", + "application/json;odata=minimalmetadata", + "application/json;odata=fullmetadata" + ], + "x-ms-enum": { + "name": "OdataMetadataFormat", + "modelAsString": true + } + }, + "topParameter": { + "name": "$top", + "in": "query", + "required": false, + "type": "integer", + "format": "int32", + "minimum": 0, + "description": "Maximum number of records to return.", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "QueryOptions" + }, + "x-ms-client-name": "Top" + }, + "selectParameter": { + "name": "$select", + "in": "query", + "required": false, + "type": "string", + "description": "Select expression using OData notation. Limits the columns on each record to just those requested, e.g. \"$select=PolicyAssignmentId, ResourceId\".", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "QueryOptions" + }, + "x-ms-client-name": "Select" + }, + "filterParameter": { + "name": "$filter", + "in": "query", + "required": false, + "type": "string", + "description": "OData filter expression.", + "x-ms-parameter-location": "method", + "x-ms-parameter-grouping": { + "name": "QueryOptions" + }, + "x-ms-client-name": "Filter" + }, + "PreferParameter": { + "name": "Prefer", + "in": "header", + "required": false, + "type": "string", + "description": "Specifies whether the response should include the inserted entity in the payload. Possible values are return-no-content and return-content.", + "x-ms-parameter-location": "method", + "x-ms-client-name": "ResponsePreference", + "enum": [ + "return-no-content", + "return-content" + ], + "x-ms-enum": { + "name": "ResponseFormat", + "modelAsString": true + } + }, + "compAclParameter": { + "name": "comp", + "in": "query", + "required": true, + "type": "string", + "enum": [ + "acl" + ], + "x-ms-parameter-location": "method", + "description": "Required query string to handle stored access policies for the table that may be used with Shared Access Signatures." + }, + "TableAcl": { + "name": "tableAcl", + "in": "body", + "schema": { + "$ref": "#/definitions/SignedIdentifiers" + }, + "x-ms-parameter-location": "method", + "description": "The acls for the table." + }, + "TableEntityProperties": { + "name": "tableEntityProperties", + "in": "body", + "schema": { + "$ref": "#/definitions/TableEntityProperties" + }, + "x-ms-parameter-location": "method", + "description": "The properties for the table entity." + }, + "tableNameParameter": { + "name": "table", + "in": "path", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The name of the table." + }, + "partitionKeyParameter": { + "name": "partitionKey", + "in": "path", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The partition key of the entity." + }, + "rowKeyParameter": { + "name": "rowKey", + "in": "path", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "The row key of the entity." + } + } +} diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts new file mode 100644 index 000000000..4dae7ca07 --- /dev/null +++ b/tests/table/apis/table.test.ts @@ -0,0 +1,20 @@ +// import { configLogger } from "../../../src/common/Logger"; +// import { StoreDestinationArray } from "../../../src/common/persistence/IExtentStore"; + +// // Set true to enable debug log +// configLogger(false); + +// describe("Table APIs test", () => { +// const host = "127.0.0.1"; +// const port = 11002; +// const metadataDbPath = "__tableTestsStorage__"; +// const persistencePath = "__tableTestsPersistence__"; + +// const DEFUALT_TABLE_PERSISTENCE_ARRAY: StoreDestinationArray = [ +// { +// locationId: "queueTest", +// locationPath: persistencePath, +// maxConcurrency: 10 +// } +// ]; +// }); From 656bf3c0044645a59fd71c298a9bffcbe937ce43 Mon Sep 17 00:00:00 2001 From: Yi Lyu <41231856+isabella0428@users.noreply.github.com> Date: Sun, 26 Jul 2020 16:25:16 +0800 Subject: [PATCH 02/57] Table (#517) * [Table] Init commit - generated from swagger * Add table draft * Finish create table * Fix tslint error * Fix windows tslint error * Fix comment and code details * Fix bugs * Remove unnecessary log * Remove certificate file * Add test and insert entity, TODO: modify context type in middleware, modify dispatch Co-authored-by: Xiaoning Liu --- package-lock.json | 125 ++++++++++++++++++ package.json | 1 + src/azurite.ts | 2 +- src/table/TableConfiguration.ts | 2 +- src/table/errors/StorageErrorFactory.ts | 44 ++++++ src/table/handlers/TableHandler.ts | 122 +++++++++++++++-- src/table/main.ts | 2 +- .../tableStorageContext.middleware.ts | 1 - src/table/persistence/ITableMetadataStore.ts | 14 +- .../persistence/LokiTableMetadataStore.ts | 55 ++++++-- src/table/utils/constants.ts | 3 + src/table/utils/utils.ts | 12 ++ tests/table/apis/table.test.ts | 76 ++++++++--- 13 files changed, 409 insertions(+), 50 deletions(-) create mode 100644 src/table/utils/utils.ts diff --git a/package-lock.json b/package-lock.json index a881ebd00..6e1b5d174 100644 --- a/package-lock.json +++ b/package-lock.json @@ -687,6 +687,72 @@ } } }, + "azure-storage": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.3.tgz", + "integrity": "sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ==", + "requires": { + "browserify-mime": "~1.2.9", + "extend": "^3.0.2", + "json-edm-parser": "0.1.2", + "md5.js": "1.3.4", + "readable-stream": "~2.0.0", + "request": "^2.86.0", + "underscore": "~1.8.3", + "uuid": "^3.0.0", + "validator": "~9.4.1", + "xml2js": "0.2.8", + "xmlbuilder": "^9.0.7" + }, + "dependencies": { + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "sax": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "validator": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==" + }, + "xml2js": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", + "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", + "requires": { + "sax": "0.5.x" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + } + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -1740,6 +1806,11 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserify-mime": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz", + "integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=" + }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -3224,6 +3295,38 @@ } } }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -3723,6 +3826,14 @@ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true }, + "json-edm-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", + "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", + "requires": { + "jsonparse": "~1.2.0" + } + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3750,6 +3861,11 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "jsonparse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz", + "integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=" + }, "jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", @@ -4153,6 +4269,15 @@ "escape-string-regexp": "^1.0.4" } }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", diff --git a/package.json b/package.json index 25c6593b5..825acd66f 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "dependencies": { "@azure/ms-rest-js": "^1.5.0", "args": "^5.0.1", + "azure-storage": "^2.10.3", "etag": "^1.8.1", "express": "^4.16.4", "jsonwebtoken": "^8.5.1", diff --git a/src/azurite.ts b/src/azurite.ts index 269bb07c0..a5ffd3bc4 100644 --- a/src/azurite.ts +++ b/src/azurite.ts @@ -77,9 +77,9 @@ async function main() { env.tableHost(), env.tablePort(), join(location, DEFAULT_TABLE_LOKI_DB_PATH), + env.debug() !== undefined, !env.silent(), undefined, - env.debug() !== undefined, await env.debug(), env.loose(), env.skipApiVersionCheck(), diff --git a/src/table/TableConfiguration.ts b/src/table/TableConfiguration.ts index 3c7c32f50..af0f6f8fb 100644 --- a/src/table/TableConfiguration.ts +++ b/src/table/TableConfiguration.ts @@ -25,9 +25,9 @@ export default class TableConfiguration extends ConfigurationBase { host: string = DEFAULT_TABLE_SERVER_HOST_NAME, port: number = DEFAULT_TABLE_LISTENING_PORT, public readonly /* Store metadata */ metadataDBPath: string = DEFAULT_TABLE_LOKI_DB_PATH, + enableDebugLog: boolean = DEFAULT_ENABLE_DEBUG_LOG, enableAccessLog: boolean = DEFAULT_ENABLE_ACCESS_LOG, accessLogWriteStream?: NodeJS.WritableStream, - enableDebugLog: boolean = DEFAULT_ENABLE_DEBUG_LOG, debugLogFilePath?: string, loose: boolean = false, skipApiVersionCheck: boolean = false, diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index dad968830..0bd871d2b 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -42,4 +42,48 @@ export default class StorageErrorFactory { contextID ); } + + public static TableAlreadyExists( + contextID: string = defaultID + ): StorageError { + return new StorageError( + 400, + "TableAlreadyExists", + "The table to create already exists.", + contextID + ); + } + + public static TableNotExist( + contextID: string = defaultID + ): StorageError { + return new StorageError( + 400, + "AccountNameEmpty", + "The table to insert doesn't exist", + contextID + ); + } + + public static insertEntityAlreadyExist( + contextID: string = defaultID + ): StorageError { + return new StorageError( + 400, + "insertEntityAlreadyExist", + "The entity to insert already exists in the table", + contextID + ); + } + + public static contentTypeNotSupported( + contextID: string = defaultID + ): StorageError { + return new StorageError( + 400, + "contentTypeNotSupported", + "Payload Type is not supported yet. Only support json.", + contextID + ); + } } diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 64dca9cab..4a78dae65 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -1,21 +1,22 @@ -import * as Models from "../generated/artifacts/models"; -import Context from "../generated/Context"; -import BaseHandler from "./BaseHandler"; - import TableStorageContext from "../context/TableStorageContext"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; +import * as Models from "../generated/artifacts/models"; +import Context from "../generated/Context"; import ITableHandler from "../generated/handlers/ITableHandler"; -import { TableModel } from "../persistence/ITableMetadataStore"; - +import { IEntity, TableModel } from "../persistence/ITableMetadataStore"; import { DEFAULT_TABLE_LISTENING_PORT, DEFAULT_TABLE_SERVER_HOST_NAME, FULL_METADATA_ACCEPT, MINIMAL_METADATA_ACCEPT, NO_METADATA_ACCEPT, + RETURN_CONTENT, + RETURN_NO_CONTENT, TABLE_API_VERSION } from "../utils/constants"; +import { newEtag } from "../utils/utils"; +import BaseHandler from "./BaseHandler"; export default class TableHandler extends BaseHandler implements ITableHandler { public async create( @@ -26,13 +27,24 @@ export default class TableHandler extends BaseHandler implements ITableHandler { const tableCtx = new TableStorageContext(context); const accountName = tableCtx.account; + const accept = context.request!.getHeader("accept"); + + if ( + accept !== NO_METADATA_ACCEPT && + accept !== MINIMAL_METADATA_ACCEPT && + accept !== FULL_METADATA_ACCEPT + ) { + throw StorageErrorFactory.contentTypeNotSupported(); + } + if (accountName === undefined) { throw StorageErrorFactory.getAccountNameEmpty(); } - const tableName = tableCtx.tableName; + // Here table name is in request body, not in url + const tableName = tableProperties.tableName; if (tableName === undefined) { - throw StorageErrorFactory.getTableNameEmpty(); + throw StorageErrorFactory.getTableNameEmpty; } const metadata = `${accountName}/$metadata#Tables/@Element`; @@ -42,7 +54,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { const table: TableModel = { account: accountName, - name: tableName, + tableName, odatametadata: metadata, odatatype: type, odataid: id, @@ -82,6 +94,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { response.odataid = `${protocol}://${host}/${id}`; response.odataeditLink = editLink; } + return response; } @@ -157,12 +170,97 @@ export default class TableHandler extends BaseHandler implements ITableHandler { } public async insertEntity( - table: string, + tableName: string, options: Models.TableInsertEntityOptionalParams, context: Context ): Promise { - // TODO - throw new NotImplementedError(); + const tableCtx = new TableStorageContext(context); + const entityString = context.request!.getBody(); + const entityObj = JSON.parse(entityString!); + const eTag = newEtag(); + + const partitionKey = entityObj.PartitionKey; + const rowKey = entityObj.RowKey; + + const entity: IEntity = { + partitionKey, + rowKey + }; + + entity.eTag = eTag; + + for (const key of Object.keys(entityObj)) { + entity[key] = entityObj[key]; + } + + const accountName = tableCtx.account; + let protocol = "http"; + let host = + DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; + if (tableCtx.request !== undefined) { + host = tableCtx.request.getHeader("host") as string; + protocol = tableCtx.request.getProtocol() as string; + } + + const metadata = `${protocol}://${host}/${accountName}/$metadata#Tables/@Element`; + const type = `${accountName}.Tables`; + const id = `${protocol}://${host}/Tables(${tableName})`; + const editLink = `Tables(${tableName})`; + + entity.metadata = metadata; + entity.type = type; + entity.id = id; + entity.editLink = editLink; + + await this.metadataStore.insertTableEntity(context, tableName, entity); + + const response: Models.TableInsertEntityResponse = { + clientRequestId: options.requestId, + requestId: tableCtx.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode: 201 + }; + + const accept = tableCtx.accept; + + // Set contentType in response according to accept + if ( + accept !== NO_METADATA_ACCEPT && + accept !== MINIMAL_METADATA_ACCEPT && + accept !== FULL_METADATA_ACCEPT + ) { + throw StorageErrorFactory.contentTypeNotSupported(); + } + + response.contentType = "application/json"; + + if (context.request!.getHeader("Prefer") === RETURN_NO_CONTENT) { + response.statusCode = 204; + response.preferenceApplied = RETURN_NO_CONTENT; + } + + if (context.request!.getHeader("Prefer") === RETURN_CONTENT) { + response.statusCode = 201; + response.preferenceApplied = "return-content"; + + if (accept === MINIMAL_METADATA_ACCEPT) { + response["odata.metadata"] = metadata; + } + + if (accept === FULL_METADATA_ACCEPT) { + response["odata.metadata"] = metadata; + response["odata.type"] = type; + response["odata.id"] = id; + response["odata.etag"] = eTag; + response["odata.editLink"] = editLink; + } + + for (const key of Object.keys(entityObj)) { + response[key] = entityObj[key]; + } + } + return response; } public async getAccessPolicy( diff --git a/src/table/main.ts b/src/table/main.ts index 348d2fe62..5700c7c84 100644 --- a/src/table/main.ts +++ b/src/table/main.ts @@ -34,9 +34,9 @@ async function main() { env.tableHost(), env.tablePort(), join(location, DEFAULT_TABLE_LOKI_DB_PATH), + (await env.debug()) !== undefined, !env.silent(), undefined, - (await env.debug()) !== undefined, await env.debug(), env.loose(), env.skipApiVersionCheck() diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index 8f15ef657..7fd476485 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -59,7 +59,6 @@ export function tableStorageContextMiddleware( const [account, table] = extractStoragePartsFromPath(req.hostname, req.path); tableContext.account = account; - tableContext.tableName = table; // Emulator's URL pattern is like http://hostname[:port]/account/table // (or, alternatively, http[s]://account.localhost[:port]/table/) diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index 675890cad..aa0860310 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -6,13 +6,19 @@ import { TABLE_STATUSCODE } from "../utils/constants"; interface ITtableAdditionalProperties { tableAcl?: Models.SignedIdentifier[]; account: string; - name: string; + tableName: string; odatametadata?: string; odatatype?: string; odataid?: string; odataeditLink?: string; } +export interface IEntity { + partitionKey: string; + rowKey: string; + [propertyName: string]: string | number; +} + export type TableModel = ITtableAdditionalProperties; export default interface ITableMetadataStore { @@ -48,7 +54,11 @@ export default interface ITableMetadataStore { partitionKey: string, rowKey: string ): Promise; - insertTableEntity(context: Context, table: string): Promise; + insertTableEntity( + context: Context, + tableName: string, + entity: IEntity + ): Promise; getTableAccessPolicy( context: Context, table: string, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index 1af8c8288..c11c55ca8 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -5,7 +5,7 @@ import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; import * as Models from "../generated/artifacts/models"; import Context from "../generated/Context"; -import { TableModel } from "../persistence/ITableMetadataStore"; +import { IEntity, TableModel } from "../persistence/ITableMetadataStore"; import { TABLE_STATUSCODE } from "../utils/constants"; import ITableMetadataStore from "./ITableMetadataStore"; @@ -37,26 +37,62 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { const coll = this.db.getCollection(this.TABLE_COLLECTION); const doc = coll.findOne({ accountName: table.account, - name: table.name + name: table.tableName }); // If the metadata exists, we will throw getTableAlreadyExists error if (doc) { - throw StorageErrorFactory.getTableAlreadyExists( - context.contextID - ); + throw StorageErrorFactory.getTableAlreadyExists(context.contextID); } coll.insert(table); + + const extentColl = this.db.getCollection(table.tableName); + if (extentColl) { + throw StorageErrorFactory.TableAlreadyExists(); + } + this.db.addCollection(table.tableName); return 201; } - public async queryTable(context: Context): Promise { + public async insertTableEntity( + context: Context, + tableName: string, + entity: IEntity + ): Promise { + const tableColl = this.db.getCollection(tableName); + if (!tableColl) { + throw StorageErrorFactory.TableNotExist(); + } + + // If the entity already exists in the table, throw an error + const doc = tableColl.findOne({ + partitionKey: entity.partitionKey, + rowKey: entity.rowKey + }); + + if (doc) { + throw StorageErrorFactory.insertEntityAlreadyExist(); + } + + entity.lastModifiedTime = new Date().toUTCString(); + + // TODO: duplicate entity error + tableColl.insert(entity); + return; + } + + public async queryTable( + context: Context + ): Promise { // TODO throw new NotImplementedError(); } - public async deleteTable(context: Context, tableName: string): Promise { + public async deleteTable( + context: Context, + tableName: string + ): Promise { // TODO context: Context throw new NotImplementedError(); } @@ -110,11 +146,6 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { throw new NotImplementedError(); } - public async insertTableEntity(context: Context, table: string): Promise { - // TODO - throw new NotImplementedError(); - } - public async getTableAccessPolicy( context: Context, table: string diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index 51d83d6a9..4e917924a 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -23,3 +23,6 @@ export const HeaderConstants = { export const NO_METADATA_ACCEPT = "application/json;odata=nometadata"; export const MINIMAL_METADATA_ACCEPT = "application/json;odata=minimalmetadata"; export const FULL_METADATA_ACCEPT = "application/json;odata=fullmetadata"; + +export const RETURN_NO_CONTENT = "return-no-content"; +export const RETURN_CONTENT = "return-content"; diff --git a/src/table/utils/utils.ts b/src/table/utils/utils.ts new file mode 100644 index 000000000..7bee02b19 --- /dev/null +++ b/src/table/utils/utils.ts @@ -0,0 +1,12 @@ +export function newEtag(): string { + // Etag should match ^"0x[A-F0-9]{15,}"$ + // Date().getTime().toString(16) only has 11 digital + // so multiply a number between 70000-100000, can get a 16 based 15+ digital number + return ( + '"0x' + + (new Date().getTime() * Math.round(Math.random() * 30000 + 70000)) + .toString(16) + .toUpperCase() + + '"' + ); +} diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index 4dae7ca07..d9d3d295f 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -1,20 +1,56 @@ -// import { configLogger } from "../../../src/common/Logger"; -// import { StoreDestinationArray } from "../../../src/common/persistence/IExtentStore"; - -// // Set true to enable debug log -// configLogger(false); - -// describe("Table APIs test", () => { -// const host = "127.0.0.1"; -// const port = 11002; -// const metadataDbPath = "__tableTestsStorage__"; -// const persistencePath = "__tableTestsPersistence__"; - -// const DEFUALT_TABLE_PERSISTENCE_ARRAY: StoreDestinationArray = [ -// { -// locationId: "queueTest", -// locationPath: persistencePath, -// maxConcurrency: 10 -// } -// ]; -// }); +import * as assert from "assert"; +import * as Azure from "azure-storage"; + +import { configLogger } from "../../../src/common/Logger"; +import TableConfiguration from "../../../src/table/TableConfiguration"; +import TableServer from "../../../src/table/TableServer"; +import { TABLE_API_VERSION } from "../../../src/table/utils/constants"; +import { + EMULATOR_ACCOUNT_KEY, + EMULATOR_ACCOUNT_NAME, + getUniqueName +} from "../../testutils"; + +// Set true to enable debug log +configLogger(false); + +describe("table APIs test", () => { + // TODO: Create a server factory as tests utils + const protocol = "http"; + const host = "127.0.0.1"; + const port = 11002; + const metadataDbPath = "__tableTestsStorage__"; + + const config = new TableConfiguration(host, port, metadataDbPath, false); + + let server: TableServer; + const tableName: string = getUniqueName("table"); + const accountName = EMULATOR_ACCOUNT_NAME; + const sharedKey = EMULATOR_ACCOUNT_KEY; + const connectionString = + `DefaultEndpointsProtocol=${protocol};AccountName=${accountName};` + + `AccountKey=${sharedKey};TableEndpoint=${protocol}://${host}:${port}/${accountName};`; + + before(async () => { + server = new TableServer(config); + await server.start(); + }); + + it("createTable @loki", done => { + const tableService = Azure.createTableService(connectionString); + + tableService.createTable(tableName, (error, result, response) => { + if (!error) { + assert.equal(result.TableName, tableName); + assert.equal(result.statusCode, 201); + const headers = response.headers!; + assert.equal(headers["x-ms-version"], TABLE_API_VERSION); + } + done(); + }); + }); + + after(async () => { + await server.close(); + }); +}); From cf6dd1d3b3a84b30a8e8b14b6c2b94f794a64e34 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Sun, 26 Jul 2020 16:31:46 +0800 Subject: [PATCH 03/57] Update serializer log format (#518) --- src/blob/generated/utils/serializer.ts | 5 ++++- src/queue/generated/utils/serializer.ts | 5 ++++- src/table/generated/utils/serializer.ts | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/blob/generated/utils/serializer.ts b/src/blob/generated/utils/serializer.ts index f6006f3a7..9702cf081 100644 --- a/src/blob/generated/utils/serializer.ts +++ b/src/blob/generated/utils/serializer.ts @@ -136,7 +136,10 @@ export async function deserialize( const body = await readRequestIntoText(req); logger.debug( - `deserialize(): Raw request body string is ${body}`, + `deserialize(): Raw request body string is (removed all empty characters) ${body.replace( + /\s/g, + "" + )}`, context.contextId ); diff --git a/src/queue/generated/utils/serializer.ts b/src/queue/generated/utils/serializer.ts index 81aac9a11..e2f0609f0 100644 --- a/src/queue/generated/utils/serializer.ts +++ b/src/queue/generated/utils/serializer.ts @@ -136,7 +136,10 @@ export async function deserialize( const body = await readRequestIntoText(req); logger.debug( - `deserialize(): Raw request body string is ${body}`, + `deserialize(): Raw request body string is (removed all empty characters) ${body.replace( + /\s/g, + "" + )}`, context.contextID ); diff --git a/src/table/generated/utils/serializer.ts b/src/table/generated/utils/serializer.ts index 81aac9a11..e2f0609f0 100644 --- a/src/table/generated/utils/serializer.ts +++ b/src/table/generated/utils/serializer.ts @@ -136,7 +136,10 @@ export async function deserialize( const body = await readRequestIntoText(req); logger.debug( - `deserialize(): Raw request body string is ${body}`, + `deserialize(): Raw request body string is (removed all empty characters) ${body.replace( + /\s/g, + "" + )}`, context.contextID ); From 241824e4a13268d309c6c03a603a5b92188d868b Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Sun, 26 Jul 2020 22:04:27 +0800 Subject: [PATCH 04/57] Generated code fix for table (#519) * Add Table debug settings; Customize Table StorageError JSON format; Serlizer supports JSON serialize; TableHandler content-type setttings; Workaround isXML specification; * Make sure each API dispath and serialize/deserialize properly * isURITemplateMatch strict match to false * Blob serializer fix * Add indexs for Table collection * Bring queue dispath URI validate to strict (TODO: inconsistency between table/blob/queue, rewrite URI match logic) * Add table test into pipeline CI --- .vscode/launch.json | 12 ++ azure-pipelines.yml | 87 ++++++++ src/blob/generated/ExpressResponseAdapter.ts | 4 + src/blob/generated/IResponse.ts | 1 + src/blob/generated/utils/serializer.ts | 36 ++++ src/blob/generated/utils/utils.ts | 2 +- src/queue/generated/ExpressResponseAdapter.ts | 4 + src/queue/generated/IResponse.ts | 1 + src/queue/generated/utils/serializer.ts | 36 ++++ src/table/TableRequestListenerFactory.ts | 22 ++ src/table/context/TableStorageContext.ts | 16 ++ src/table/errors/StorageError.ts | 46 ++++- src/table/errors/StorageErrorFactory.ts | 57 +++--- src/table/generated/ExpressResponseAdapter.ts | 4 + src/table/generated/IResponse.ts | 1 + src/table/generated/utils/serializer.ts | 36 ++++ src/table/generated/utils/utils.ts | 2 +- src/table/handlers/ServiceHandler.ts | 6 +- src/table/handlers/TableHandler.ts | 192 +++++++++++++++--- .../tableStorageContext.middleware.ts | 71 ++++++- src/table/persistence/ITableMetadataStore.ts | 4 +- .../persistence/LokiTableMetadataStore.ts | 19 +- src/table/utils/constants.ts | 3 +- tests/table/apis/table.test.ts | 6 + 24 files changed, 580 insertions(+), 88 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index b802fe9c2..88cafd4a0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -108,6 +108,18 @@ }, "outputCapture": "std" }, + { + "type": "node", + "request": "launch", + "name": "Azurite Table Service - Loki", + "cwd": "${workspaceFolder}", + "runtimeArgs": ["-r", "ts-node/register"], + "args": ["${workspaceFolder}/src/table/main.ts", "-d", "debug.log"], + "env": { + "AZURITE_ACCOUNTS": "" + }, + "outputCapture": "std" + }, { "type": "node", "request": "launch", diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6491627fd..e5f01163b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -220,6 +220,93 @@ jobs: displayName: "npm run test:queue" env: {} + - job: tabletestlinux + displayName: Table Test Linux + pool: + vmImage: "ubuntu-16.04" + strategy: + matrix: + node_8_x: + node_version: 8.x + node_10_x: + node_version: 10.x + node_12_x: + node_version: 12.x + steps: + - task: NodeTool@0 + inputs: + versionSpec: "$(node_version)" + displayName: "Install Node.js" + + - script: | + npm ci + workingDirectory: "./" + displayName: "npm ci" + + - script: | + npm run test:table + workingDirectory: "./" + displayName: "npm run test:table" + env: {} + + - job: tabletestwin + displayName: Table Test Windows + pool: + vmImage: "vs2017-win2016" + strategy: + matrix: + node_8_x: + node_version: 8.x + node_10_x: + node_version: 10.x + node_12_x: + node_version: 12.x + steps: + - task: NodeTool@0 + inputs: + versionSpec: "$(node_version)" + displayName: "Install Node.js" + + - script: | + npm ci + workingDirectory: "./" + displayName: "npm ci" + + - script: | + npm run test:table + workingDirectory: "./" + displayName: "npm run test:table" + env: {} + + - job: tabletestmac + displayName: Table Test Mac + pool: + vmImage: "macOS-10.14" + strategy: + matrix: + node_8_x: + node_version: 8.x + node_10_x: + node_version: 10.x + node_12_x: + node_version: 12.x + steps: + - task: NodeTool@0 + inputs: + versionSpec: "$(node_version)" + displayName: "Install Node.js" + + - script: | + npm ci + workingDirectory: "./" + displayName: "npm ci" + + - script: | + npm run test:table + workingDirectory: "./" + displayName: "npm run test:table" + env: {} + - job: azuritenodejslinux displayName: Azurite Linux pool: diff --git a/src/blob/generated/ExpressResponseAdapter.ts b/src/blob/generated/ExpressResponseAdapter.ts index d938a41ea..fd9bece7d 100644 --- a/src/blob/generated/ExpressResponseAdapter.ts +++ b/src/blob/generated/ExpressResponseAdapter.ts @@ -43,6 +43,10 @@ export default class ExpressResponseAdapter implements IResponse { return this; } + public getHeader(field: string): number | string | string[] | undefined { + return this.res.getHeader(field); + } + public getHeaders(): OutgoingHttpHeaders { return this.res.getHeaders(); } diff --git a/src/blob/generated/IResponse.ts b/src/blob/generated/IResponse.ts index d611d9618..71e5df921 100644 --- a/src/blob/generated/IResponse.ts +++ b/src/blob/generated/IResponse.ts @@ -9,6 +9,7 @@ export default interface IResponse { field: string, value?: string | string[] | undefined | number | boolean ): IResponse; + getHeader(field: string): number | string | string[] | undefined; getHeaders(): OutgoingHttpHeaders; headersSent(): boolean; setContentType(value: string | undefined): IResponse; diff --git a/src/blob/generated/utils/serializer.ts b/src/blob/generated/utils/serializer.ts index 9702cf081..85197a463 100644 --- a/src/blob/generated/utils/serializer.ts +++ b/src/blob/generated/utils/serializer.ts @@ -324,6 +324,42 @@ export async function serialize( logger.info(`Serializer: Start returning stream body.`, context.contextId); } + // Serialize JSON bodies + if ( + !spec.isXML && + responseSpec.bodyMapper && + responseSpec.bodyMapper.type.name !== "Stream" + ) { + let body = spec.serializer.serialize( + responseSpec.bodyMapper!, + handlerResponse + ); + + // When root element is sequence type, should wrap with because serialize() doesn't do that + if (responseSpec.bodyMapper!.type.name === "Sequence") { + const sequenceElementName = responseSpec.bodyMapper!.xmlElementName; + if (sequenceElementName !== undefined) { + const newBody = {} as any; + newBody[sequenceElementName] = body; + body = newBody; + } + } + + if (!res.getHeader("content-type")) { + res.setContentType("application/json"); + } + + const jsonBody = JSON.stringify(body); + + // TODO: Should send response in a serializer? + res.getBodyStream().write(jsonBody); + logger.debug( + `Serializer: Raw response body string is ${jsonBody}`, + context.contextId + ); + logger.info(`Serializer: Start returning stream body.`, context.contextId); + } + // Serialize stream body // TODO: Move to end middleware for end tracking if ( diff --git a/src/blob/generated/utils/utils.ts b/src/blob/generated/utils/utils.ts index 014377abe..8907780e5 100644 --- a/src/blob/generated/utils/utils.ts +++ b/src/blob/generated/utils/utils.ts @@ -3,7 +3,7 @@ import URITemplate from "uri-templates"; export function isURITemplateMatch(url: string, template: string): boolean { const uriTemplate = URITemplate(template); // TODO: Fixing $ parsing issue such as $logs container cannot work in strict mode issue - const result = (uriTemplate.fromUri as any)(url, { strict: true }); + const result = (uriTemplate.fromUri as any)(url, { strict: false }); if (result === undefined) { return false; } diff --git a/src/queue/generated/ExpressResponseAdapter.ts b/src/queue/generated/ExpressResponseAdapter.ts index d938a41ea..fd9bece7d 100644 --- a/src/queue/generated/ExpressResponseAdapter.ts +++ b/src/queue/generated/ExpressResponseAdapter.ts @@ -43,6 +43,10 @@ export default class ExpressResponseAdapter implements IResponse { return this; } + public getHeader(field: string): number | string | string[] | undefined { + return this.res.getHeader(field); + } + public getHeaders(): OutgoingHttpHeaders { return this.res.getHeaders(); } diff --git a/src/queue/generated/IResponse.ts b/src/queue/generated/IResponse.ts index d611d9618..71e5df921 100644 --- a/src/queue/generated/IResponse.ts +++ b/src/queue/generated/IResponse.ts @@ -9,6 +9,7 @@ export default interface IResponse { field: string, value?: string | string[] | undefined | number | boolean ): IResponse; + getHeader(field: string): number | string | string[] | undefined; getHeaders(): OutgoingHttpHeaders; headersSent(): boolean; setContentType(value: string | undefined): IResponse; diff --git a/src/queue/generated/utils/serializer.ts b/src/queue/generated/utils/serializer.ts index e2f0609f0..267659fa5 100644 --- a/src/queue/generated/utils/serializer.ts +++ b/src/queue/generated/utils/serializer.ts @@ -324,6 +324,42 @@ export async function serialize( logger.info(`Serializer: Start returning stream body.`, context.contextID); } + // Serialize JSON bodies + if ( + !spec.isXML && + responseSpec.bodyMapper && + responseSpec.bodyMapper.type.name !== "Stream" + ) { + let body = spec.serializer.serialize( + responseSpec.bodyMapper!, + handlerResponse + ); + + // When root element is sequence type, should wrap with because serialize() doesn't do that + if (responseSpec.bodyMapper!.type.name === "Sequence") { + const sequenceElementName = responseSpec.bodyMapper!.xmlElementName; + if (sequenceElementName !== undefined) { + const newBody = {} as any; + newBody[sequenceElementName] = body; + body = newBody; + } + } + + if (!res.getHeader("content-type")) { + res.setContentType("application/json"); + } + + const jsonBody = JSON.stringify(body); + + // TODO: Should send response in a serializer? + res.getBodyStream().write(jsonBody); + logger.debug( + `Serializer: Raw response body string is ${jsonBody}`, + context.contextID + ); + logger.info(`Serializer: Start returning stream body.`, context.contextID); + } + // Serialize stream body // TODO: Move to end middleware for end tracking if ( diff --git a/src/table/TableRequestListenerFactory.ts b/src/table/TableRequestListenerFactory.ts index fc9db3a1e..ed409151f 100644 --- a/src/table/TableRequestListenerFactory.ts +++ b/src/table/TableRequestListenerFactory.ts @@ -1,8 +1,12 @@ import express from "express"; import { RequestListener } from "http"; +import { OperationSpec } from "@azure/ms-rest-js/es/lib/operationSpec"; + import IRequestListenerFactory from "../common/IRequestListenerFactory"; import logger from "../common/Logger"; +import { Operation } from "./generated/artifacts/operation"; +import Specifications from "./generated/artifacts/specifications"; import ExpressMiddlewareFactory from "./generated/ExpressMiddlewareFactory"; import IHandlers from "./generated/handlers/IHandlers"; import MiddlewareFactory from "./generated/MiddlewareFactory"; @@ -32,6 +36,24 @@ export default class TableRequestListenerFactory ) {} public createRequestListener(): RequestListener { + // TODO: Workarounds for generated specification isXML issue. Ideally should fix in generator. + type MutableSpecification = { + -readonly [K in keyof OperationSpec]: OperationSpec[K]; + }; + [ + Operation.Table_Create, + Operation.Table_Query, + Operation.Table_Delete, + Operation.Table_QueryEntities, + Operation.Table_QueryEntitiesWithPartitionAndRowKey, + Operation.Table_UpdateEntity, + Operation.Table_MergeEntity, + Operation.Table_DeleteEntity, + Operation.Table_InsertEntity + ].forEach(operation => { + (Specifications[operation] as MutableSpecification).isXML = false; + }); + const app = express().disable("x-powered-by"); // MiddlewareFactory is a factory to create auto-generated middleware diff --git a/src/table/context/TableStorageContext.ts b/src/table/context/TableStorageContext.ts index 659659660..0c9b0dc81 100644 --- a/src/table/context/TableStorageContext.ts +++ b/src/table/context/TableStorageContext.ts @@ -17,6 +17,22 @@ export default class TableStorageContext extends Context { this.context.tableName = tableName; } + public get partitionKey(): string | undefined { + return this.context.partitionKey; + } + + public set partitionKey(partitionKey: string | undefined) { + this.context.partitionKey = partitionKey; + } + + public get rowKey(): string | undefined { + return this.context.rowKey; + } + + public set rowKey(rowKey: string | undefined) { + this.context.rowKey = rowKey; + } + public get xMsRequestID(): string | undefined { return this.contextID; } diff --git a/src/table/errors/StorageError.ts b/src/table/errors/StorageError.ts index 153c11dc2..d6c4671ab 100644 --- a/src/table/errors/StorageError.ts +++ b/src/table/errors/StorageError.ts @@ -1,4 +1,10 @@ -import { TABLE_API_VERSION } from "../../table/utils/constants"; +import { + FULL_METADATA_ACCEPT, + MINIMAL_METADATA_ACCEPT, + NO_METADATA_ACCEPT, + TABLE_API_VERSION +} from "../../table/utils/constants"; +import Context from "../generated/Context"; import MiddlewareError from "../generated/errors/MiddlewareError"; import { jsonToXML } from "../generated/utils/xml"; @@ -23,6 +29,7 @@ export default class StorageError extends MiddlewareError { * @param {string} storageRequestID Azure Storage server request ID * @param {{ [key: string]: string }} [storageAdditionalErrorMessages={}] * Additional error messages will be included in XML body + * @param [Context] context * @memberof StorageError */ constructor( @@ -30,12 +37,31 @@ export default class StorageError extends MiddlewareError { storageErrorCode: string, storageErrorMessage: string, storageRequestID: string, - storageAdditionalErrorMessages: { [key: string]: string } = {} + storageAdditionalErrorMessages: { [key: string]: string } = {}, + context?: Context ) { - const bodyInJSON: any = { - Code: storageErrorCode, - Message: `${storageErrorMessage}\nRequestId:${storageRequestID}\nTime:${new Date().toISOString()}` - }; + let isJSON = false; + const accept = context ? context.request!.getHeader("accept") : undefined; + if ( + accept === NO_METADATA_ACCEPT || + accept === MINIMAL_METADATA_ACCEPT || + accept === FULL_METADATA_ACCEPT + ) { + isJSON = true; + } + + const bodyInJSON: any = isJSON + ? { + code: storageErrorCode, + message: { + lang: "en-US", + value: `${storageErrorMessage}\nRequestId:${storageRequestID}\nTime:${new Date().toISOString()}` + } + } + : { + Code: storageErrorCode, + Message: `${storageErrorMessage}\nRequestId:${storageRequestID}\nTime:${new Date().toISOString()}` + }; for (const key in storageAdditionalErrorMessages) { if (storageAdditionalErrorMessages.hasOwnProperty(key)) { @@ -44,7 +70,9 @@ export default class StorageError extends MiddlewareError { } } - const bodyInXML = jsonToXML({ Error: bodyInJSON }); + const body = isJSON + ? JSON.stringify({ "odata.error": bodyInJSON }) + : jsonToXML({ Error: bodyInJSON }); super( statusCode, @@ -55,8 +83,8 @@ export default class StorageError extends MiddlewareError { "x-ms-request-id": storageRequestID, "x-ms-version": TABLE_API_VERSION }, - bodyInXML, - "application/xml" + body, + isJSON ? `${accept};streaming=true;charset=utf-8` : "application/xml" ); this.name = "StorageError"; diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 0bd871d2b..496939f7e 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -5,85 +5,86 @@ * @class StorageErrorFactory */ +import Context from "../generated/Context"; import StorageError from "./StorageError"; const defaultID: string = "DefaultID"; export default class StorageErrorFactory { - public static getTableAlreadyExists( - contextID: string = defaultID - ): StorageError { + public static getTableAlreadyExists(context: Context): StorageError { return new StorageError( 409, "TableAlreadyExists", "The specified table already exists.", - contextID + context.contextID || defaultID, + undefined, + context ); } - public static getTableNameEmpty( - contextID: string = defaultID - ): StorageError { + public static getTableNameEmpty(context: Context): StorageError { return new StorageError( 400, "TableNameEmpty", "The specified table name is empty.", - contextID + context.contextID || defaultID, + undefined, + context ); } - public static getAccountNameEmpty( - contextID: string = defaultID - ): StorageError { + public static getAccountNameEmpty(context: Context): StorageError { return new StorageError( 400, "AccountNameEmpty", "The specified account name is empty.", - contextID + context.contextID || defaultID, + undefined, + context ); } - public static TableAlreadyExists( - contextID: string = defaultID - ): StorageError { + public static TableAlreadyExists(context: Context): StorageError { return new StorageError( 400, "TableAlreadyExists", "The table to create already exists.", - contextID + context.contextID || defaultID, + undefined, + context ); } - public static TableNotExist( - contextID: string = defaultID - ): StorageError { + public static TableNotExist(context: Context): StorageError { return new StorageError( 400, "AccountNameEmpty", "The table to insert doesn't exist", - contextID + context.contextID || defaultID, + undefined, + context ); } - public static insertEntityAlreadyExist( - contextID: string = defaultID - ): StorageError { + public static insertEntityAlreadyExist(context: Context): StorageError { return new StorageError( 400, "insertEntityAlreadyExist", "The entity to insert already exists in the table", - contextID + context.contextID || defaultID, + undefined, + context ); } - public static contentTypeNotSupported( - contextID: string = defaultID - ): StorageError { + public static contentTypeNotSupported(context: Context): StorageError { return new StorageError( 400, "contentTypeNotSupported", "Payload Type is not supported yet. Only support json.", - contextID + context.contextID || defaultID, + undefined, + context ); } } diff --git a/src/table/generated/ExpressResponseAdapter.ts b/src/table/generated/ExpressResponseAdapter.ts index d938a41ea..fd9bece7d 100644 --- a/src/table/generated/ExpressResponseAdapter.ts +++ b/src/table/generated/ExpressResponseAdapter.ts @@ -43,6 +43,10 @@ export default class ExpressResponseAdapter implements IResponse { return this; } + public getHeader(field: string): number | string | string[] | undefined { + return this.res.getHeader(field); + } + public getHeaders(): OutgoingHttpHeaders { return this.res.getHeaders(); } diff --git a/src/table/generated/IResponse.ts b/src/table/generated/IResponse.ts index d611d9618..71e5df921 100644 --- a/src/table/generated/IResponse.ts +++ b/src/table/generated/IResponse.ts @@ -9,6 +9,7 @@ export default interface IResponse { field: string, value?: string | string[] | undefined | number | boolean ): IResponse; + getHeader(field: string): number | string | string[] | undefined; getHeaders(): OutgoingHttpHeaders; headersSent(): boolean; setContentType(value: string | undefined): IResponse; diff --git a/src/table/generated/utils/serializer.ts b/src/table/generated/utils/serializer.ts index e2f0609f0..267659fa5 100644 --- a/src/table/generated/utils/serializer.ts +++ b/src/table/generated/utils/serializer.ts @@ -324,6 +324,42 @@ export async function serialize( logger.info(`Serializer: Start returning stream body.`, context.contextID); } + // Serialize JSON bodies + if ( + !spec.isXML && + responseSpec.bodyMapper && + responseSpec.bodyMapper.type.name !== "Stream" + ) { + let body = spec.serializer.serialize( + responseSpec.bodyMapper!, + handlerResponse + ); + + // When root element is sequence type, should wrap with because serialize() doesn't do that + if (responseSpec.bodyMapper!.type.name === "Sequence") { + const sequenceElementName = responseSpec.bodyMapper!.xmlElementName; + if (sequenceElementName !== undefined) { + const newBody = {} as any; + newBody[sequenceElementName] = body; + body = newBody; + } + } + + if (!res.getHeader("content-type")) { + res.setContentType("application/json"); + } + + const jsonBody = JSON.stringify(body); + + // TODO: Should send response in a serializer? + res.getBodyStream().write(jsonBody); + logger.debug( + `Serializer: Raw response body string is ${jsonBody}`, + context.contextID + ); + logger.info(`Serializer: Start returning stream body.`, context.contextID); + } + // Serialize stream body // TODO: Move to end middleware for end tracking if ( diff --git a/src/table/generated/utils/utils.ts b/src/table/generated/utils/utils.ts index 014377abe..8907780e5 100644 --- a/src/table/generated/utils/utils.ts +++ b/src/table/generated/utils/utils.ts @@ -3,7 +3,7 @@ import URITemplate from "uri-templates"; export function isURITemplateMatch(url: string, template: string): boolean { const uriTemplate = URITemplate(template); // TODO: Fixing $ parsing issue such as $logs container cannot work in strict mode issue - const result = (uriTemplate.fromUri as any)(url, { strict: true }); + const result = (uriTemplate.fromUri as any)(url, { strict: false }); if (result === undefined) { return false; } diff --git a/src/table/handlers/ServiceHandler.ts b/src/table/handlers/ServiceHandler.ts index 6b12f9a22..45db071d5 100644 --- a/src/table/handlers/ServiceHandler.ts +++ b/src/table/handlers/ServiceHandler.ts @@ -11,7 +11,7 @@ export default class ServiceHandler extends BaseHandler options: Models.ServiceSetPropertiesOptionalParams, context: Context ): Promise { - // TODO + // TODO Refer to Blob/Queue ServiceHandler implementation throw new NotImplementedError(); } @@ -19,7 +19,7 @@ export default class ServiceHandler extends BaseHandler options: Models.ServiceGetPropertiesOptionalParams, context: Context ): Promise { - // TODO + // TODO Refer to Blob/Queue ServiceHandler implementation throw new NotImplementedError(); } @@ -27,7 +27,7 @@ export default class ServiceHandler extends BaseHandler options: Models.ServiceGetStatisticsOptionalParams, context: Context ): Promise { - // TODO + // TODO Refer to Blob/Queue ServiceHandler implementation throw new NotImplementedError(); } } diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 4a78dae65..d19b793a2 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -34,11 +34,11 @@ export default class TableHandler extends BaseHandler implements ITableHandler { accept !== MINIMAL_METADATA_ACCEPT && accept !== FULL_METADATA_ACCEPT ) { - throw StorageErrorFactory.contentTypeNotSupported(); + throw StorageErrorFactory.contentTypeNotSupported(context); } if (accountName === undefined) { - throw StorageErrorFactory.getAccountNameEmpty(); + throw StorageErrorFactory.getAccountNameEmpty(context); } // Here table name is in request body, not in url @@ -95,6 +95,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { response.odataeditLink = editLink; } + context.response!.setContentType(accept); return response; } @@ -103,6 +104,23 @@ export default class TableHandler extends BaseHandler implements ITableHandler { context: Context ): Promise { // TODO + // e.g + // return { + // statusCode: 200, + // clientRequestId: "clientRequestId", + // requestId: "requestId", + // version: "version", + // xMsContinuationNextTableName: "xMsContinuationNextTableName", + // odatametadata: "odatametadata", + // value: [ + // { + // tableName: "tableName", + // odatatype: "odatatype", + // odataid: "odataid", + // odataeditLink: "odataeditLink" + // } + // ] + // }; throw new NotImplementedError(); } @@ -111,6 +129,17 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableDeleteMethodOptionalParams, context: Context ): Promise { + // e.g + // const tableCtx = new TableStorageContext(context); + // const accountName = tableCtx.account; + // const tableName = tableCtx.tableName; // Get tableName from context + // return { + // statusCode: 204, + // clientRequestId: "clientRequestId", + // requestId: "requestId", + // version: "version" + // }; + // TODO throw new NotImplementedError(); } @@ -120,80 +149,170 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableQueryEntitiesOptionalParams, context: Context ): Promise { + // e.g + // const tableCtx = new TableStorageContext(context); + // const accountName = tableCtx.account; + // const tableName = tableCtx.tableName; // Get tableName from context + // return { + // statusCode: 200, + // date: tableCtx.startTime, + // clientRequestId: "clientRequestId", + // requestId: "requestId", + // version: "version", + // xMsContinuationNextPartitionKey: "xMsContinuationNextPartitionKey", + // xMsContinuationNextRowKey: "xMsContinuationNextRowKey", + // odatametadata: "odatametadata", + // value: [ + // { + // property1: "property1" + accountName, + // property2: "property2" + tableName, + // property3: "property3" + // }, + // { + // property1: "property1" + // } + // ] + // }; // TODO throw new NotImplementedError(); } public async queryEntitiesWithPartitionAndRowKey( - table: string, - partitionKey: string, - rowKey: string, + _table: string, + _partitionKey: string, + _rowKey: string, options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, context: Context ): Promise { + // e.g + // const tableCtx = new TableStorageContext(context); + // const accountName = tableCtx.account; + // const tableName = tableCtx.tableName; // Get tableName from context + // const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context + // const rowKey = tableCtx.rowKey!; // Get rowKey from context + // return { + // statusCode: 200, + // date: tableCtx.startTime, + // clientRequestId: "clientRequestId", + // requestId: "requestId", + // version: "version", + // xMsContinuationNextPartitionKey: partitionKeyFromContext, + // xMsContinuationNextRowKey: rowKeyFromContext, + // odatametadata: "odatametadata", + // value: [ + // { + // property1: "property1" + accountName, + // property2: "property2" + tableName, + // property3: "property3" + // }, + // { + // property1: "property1" + // } + // ] + // }; // TODO throw new NotImplementedError(); } public async updateEntity( - table: string, - partitionKey: string, - rowKey: string, + _table: string, + _partitionKey: string, + _rowKey: string, options: Models.TableUpdateEntityOptionalParams, context: Context ): Promise { + // e.g + // const tableCtx = new TableStorageContext(context); + // const accountName = tableCtx.account; + // const tableName = tableCtx.tableName; // Get tableName from context + // const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context + // const rowKey = tableCtx.rowKey!; // Get rowKey from context + // const entity = options.tableEntityProperties!; + // return { + // statusCode: 204, + // date: tableCtx.startTime, + // clientRequestId: "clientRequestId", + // requestId: "requestId", + // version: "version" + // }; // TODO throw new NotImplementedError(); } public async mergeEntity( - table: string, - partitionKey: string, - rowKey: string, + _table: string, + _partitionKey: string, + _rowKey: string, options: Models.TableMergeEntityOptionalParams, context: Context ): Promise { + // e.g + // const tableCtx = new TableStorageContext(context); + // const accountName = tableCtx.account; + // const tableName = tableCtx.tableName; // Get tableName from context + // const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context + // const rowKey = tableCtx.rowKey!; // Get rowKey from context + // const entity = options.tableEntityProperties!; + // return { + // statusCode: 204, + // date: tableCtx.startTime, + // clientRequestId: "clientRequestId", + // requestId: "requestId", + // version: "version" + // }; // TODO throw new NotImplementedError(); } public async deleteEntity( - table: string, - partitionKey: string, - rowKey: string, + _table: string, + _partitionKey: string, + _rowKey: string, ifMatch: string, options: Models.TableDeleteEntityOptionalParams, context: Context ): Promise { + // e.g + // const tableCtx = new TableStorageContext(context); + // const accountName = tableCtx.account; + // const tableName = tableCtx.tableName; // Get tableName from context + // const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context + // const rowKey = tableCtx.rowKey!; // Get rowKey from context + // return { + // statusCode: 204, + // date: tableCtx.startTime, + // clientRequestId: "clientRequestId", + // requestId: "requestId", + // version: "version" + // }; // TODO throw new NotImplementedError(); } public async insertEntity( - tableName: string, + _tableName: string, options: Models.TableInsertEntityOptionalParams, context: Context ): Promise { const tableCtx = new TableStorageContext(context); - const entityString = context.request!.getBody(); - const entityObj = JSON.parse(entityString!); - const eTag = newEtag(); + const accountName = tableCtx.account; + const tableName = tableCtx.tableName!; // Get tableName from context - const partitionKey = entityObj.PartitionKey; - const rowKey = entityObj.RowKey; + if ( + !options.tableEntityProperties || + !options.tableEntityProperties.PartitionKey || + !options.tableEntityProperties.RowKey + ) { + // TODO: Check error code and error message + throw new Error("Invalid entity"); + } - const entity: IEntity = { - partitionKey, - rowKey - }; + const entity: IEntity = options.tableEntityProperties as IEntity; + const eTag = newEtag(); entity.eTag = eTag; - for (const key of Object.keys(entityObj)) { - entity[key] = entityObj[key]; - } - - const accountName = tableCtx.account; + // TODO: Move logic to get host into utility methods let protocol = "http"; let host = DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; @@ -230,7 +349,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { accept !== MINIMAL_METADATA_ACCEPT && accept !== FULL_METADATA_ACCEPT ) { - throw StorageErrorFactory.contentTypeNotSupported(); + throw StorageErrorFactory.contentTypeNotSupported(context); } response.contentType = "application/json"; @@ -256,8 +375,9 @@ export default class TableHandler extends BaseHandler implements ITableHandler { response["odata.editLink"] = editLink; } - for (const key of Object.keys(entityObj)) { - response[key] = entityObj[key]; + // TODO: Filter out non entity properties in response body (how about update swagger to response stream type?) + for (const key of Object.keys(entity)) { + response[key] = entity[key]; } } return response; @@ -268,6 +388,10 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableGetAccessPolicyOptionalParams, context: Context ): Promise { + // e.g + // const tableCtx = new TableStorageContext(context); + // const accountName = tableCtx.account; + // const tableName = tableCtx.tableName; // Get tableName from context // TODO throw new NotImplementedError(); } @@ -277,6 +401,10 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableSetAccessPolicyOptionalParams, context: Context ): Promise { + // e.g + // const tableCtx = new TableStorageContext(context); + // const accountName = tableCtx.account; + // const tableName = tableCtx.tableName; // Get tableName from context // TODO throw new NotImplementedError(); } diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index 7fd476485..025982d01 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -31,7 +31,7 @@ export function tableStorageContextMiddleware( // Set server header in every Azurite response res.setHeader( HeaderConstants.SERVER, - `Azurite-table/${HeaderConstants.VERSION}` + `Azurite-Table/${HeaderConstants.VERSION}` ); const requestID = uuid(); @@ -56,7 +56,69 @@ export function tableStorageContextMiddleware( requestID ); - const [account, table] = extractStoragePartsFromPath(req.hostname, req.path); + const [account, tableSection] = extractStoragePartsFromPath( + req.hostname, + req.path + ); + + // Candidate tableSection + // undefined - Set Table Service Properties + // Tables - Create Tables, Query Tables + // Tables('mytable') - Delete Tables + // mytable - Get/Set Table ACL, Insert Entity + // mytable(PartitionKey='',RowKey='') - + // Query Entities, Update Entity, Merge Entity, Delete Entity + // mytable() - Query Entities + // TODO: Not allowed create Table with Tables as name + if (tableSection === undefined) { + // Service level operation + tableContext.tableName = undefined; + } else if (tableSection === "Tables") { + // Table name in request body + tableContext.tableName = undefined; + } else if ( + tableSection.startsWith("Tables('") && + tableSection.endsWith("')") + ) { + // Tables('mytable') + tableContext.tableName = tableSection.substring(8, tableSection.length - 2); + } else if (!tableSection.includes("(") && !tableSection.includes(")")) { + // mytable + tableContext.tableName = tableSection; + } else if ( + tableSection.includes("(") && + tableSection.includes(")") && + tableSection.includes("PartitionKey='") && + tableSection.includes("RowKey='") + ) { + // mytable(PartitionKey='',RowKey='') + tableContext.tableName = tableSection.substring( + 0, + tableSection.indexOf("(") + ); + const firstQuoteIndex = tableSection.indexOf("'"); + const secondQuoteIndex = tableSection.indexOf("'", firstQuoteIndex + 1); + const thridQuoteIndex = tableSection.indexOf("'", secondQuoteIndex + 1); + const fourthQuoteIndex = tableSection.indexOf("'", thridQuoteIndex + 1); + tableContext.partitionKey = tableSection.substring( + firstQuoteIndex + 1, + secondQuoteIndex + ); + tableContext.rowKey = tableSection.substring( + thridQuoteIndex + 1, + fourthQuoteIndex + ); + } else { + logger.error( + `tableStorageContextMiddleware: Cannot extract table name from URL path=${req.path}`, + requestID + ); + return next( + new Error( + `tableStorageContextMiddleware: Cannot extract table name from URL path=${req.path}` + ) + ); + } tableContext.account = account; @@ -64,10 +126,11 @@ export function tableStorageContextMiddleware( // (or, alternatively, http[s]://account.localhost[:port]/table/) // Create a router to exclude account name from req.path, as url path in swagger doesn't include account // Exclude account name from req.path for dispatchMiddleware - tableContext.dispatchPattern = table !== undefined ? `/Tables` : "/"; + tableContext.dispatchPattern = + tableSection !== undefined ? `/${tableSection}` : "/"; logger.info( - `tableStorageContextMiddleware: Account=${account} tableName=${table}}`, + `tableStorageContextMiddleware: Account=${account} tableName=${tableSection}}`, requestID ); next(); diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index aa0860310..88c813061 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -14,8 +14,8 @@ interface ITtableAdditionalProperties { } export interface IEntity { - partitionKey: string; - rowKey: string; + PartitionKey: string; + RowKey: string; [propertyName: string]: string | number; } diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index c11c55ca8..05c11dd90 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -42,16 +42,22 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { // If the metadata exists, we will throw getTableAlreadyExists error if (doc) { - throw StorageErrorFactory.getTableAlreadyExists(context.contextID); + throw StorageErrorFactory.getTableAlreadyExists(context); } coll.insert(table); const extentColl = this.db.getCollection(table.tableName); if (extentColl) { - throw StorageErrorFactory.TableAlreadyExists(); + throw StorageErrorFactory.TableAlreadyExists(context); } - this.db.addCollection(table.tableName); + + this.db.addCollection(table.tableName, { + // Optimization for indexing and searching + // https://rawgit.com/techfort/LokiJS/master/jsdoc/tutorial-Indexing%20and%20Query%20performance.html + indices: ["ParititionKey", "RowKey"] + }); // Optimize for find operation + return 201; } @@ -62,7 +68,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { ): Promise { const tableColl = this.db.getCollection(tableName); if (!tableColl) { - throw StorageErrorFactory.TableNotExist(); + throw StorageErrorFactory.TableNotExist(context); } // If the entity already exists in the table, throw an error @@ -72,12 +78,11 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { }); if (doc) { - throw StorageErrorFactory.insertEntityAlreadyExist(); + throw StorageErrorFactory.insertEntityAlreadyExist(context); } - entity.lastModifiedTime = new Date().toUTCString(); + entity.lastModifiedTime = context.startTime!.toUTCString(); - // TODO: duplicate entity error tableColl.insert(entity); return; } diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index 4e917924a..948a4513a 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -17,7 +17,8 @@ export const TABLE_API_VERSION = "2019-12-12"; export const HeaderConstants = { SERVER: "Server", - VERSION: "3.8.0" + VERSION: "3.8.0", + APPLICATION_JSON: "application/json" }; export const NO_METADATA_ACCEPT = "application/json;odata=nometadata"; diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index d9d3d295f..fca04e6f2 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -37,6 +37,12 @@ describe("table APIs test", () => { }); it("createTable @loki", done => { + /* TODO: Azure Storage Table SDK doesn't support customize Accept header, + thus we cannot test following 3 OData levels and respones. + - application/json;odata=nometadata + - application/json;odata=minimalmetadata + - application/json;odata=fullmetadata + */ const tableService = Azure.createTableService(connectionString); tableService.createTable(tableName, (error, result, response) => { From 14b45a65d8f991cff8c2ab47adf2d1d69514474c Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Mon, 27 Jul 2020 15:31:22 +0800 Subject: [PATCH 05/57] Workaround InsertEntity response body issue (#521) * Workaroudn InsertEntity response body issue * Workaround for legacy table sdk accept and prefer override --- src/table/errors/StorageErrorFactory.ts | 23 +++-- src/table/generated/artifacts/models.ts | 8 +- .../generated/artifacts/specifications.ts | 10 +-- src/table/handlers/TableHandler.ts | 64 ++++++++------ src/table/persistence/ITableMetadataStore.ts | 17 ++-- .../persistence/LokiTableMetadataStore.ts | 26 +++--- swagger/table.md | 13 +++ tests/table/apis/table.test.ts | 87 ++++++++++++++++--- tests/testutils.ts | 34 ++++++++ 9 files changed, 197 insertions(+), 85 deletions(-) diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 496939f7e..928bb947e 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -4,7 +4,6 @@ * @export * @class StorageErrorFactory */ - import Context from "../generated/Context"; import StorageError from "./StorageError"; @@ -44,40 +43,40 @@ export default class StorageErrorFactory { ); } - public static TableAlreadyExists(context: Context): StorageError { + public static getTableNotExist(context: Context): StorageError { return new StorageError( 400, - "TableAlreadyExists", - "The table to create already exists.", + "AccountNameEmpty", + "The table to insert doesn't exist", context.contextID || defaultID, undefined, context ); } - public static TableNotExist(context: Context): StorageError { + public static getEntityAlreadyExist(context: Context): StorageError { return new StorageError( - 400, - "AccountNameEmpty", - "The table to insert doesn't exist", + 409, + "EntityAlreadyExist", + "The entity to insert already exists in the table", context.contextID || defaultID, undefined, context ); } - public static insertEntityAlreadyExist(context: Context): StorageError { + public static getPropertiesNeedValue(context: Context): StorageError { return new StorageError( 400, - "insertEntityAlreadyExist", - "The entity to insert already exists in the table", + "PropertiesNeedValue", + "The values are not specified for all properties in the entity.", context.contextID || defaultID, undefined, context ); } - public static contentTypeNotSupported(context: Context): StorageError { + public static getContentTypeNotSupported(context: Context): StorageError { return new StorageError( 400, "contentTypeNotSupported", diff --git a/src/table/generated/artifacts/models.ts b/src/table/generated/artifacts/models.ts index 72ed20ca2..80fd9a447 100644 --- a/src/table/generated/artifacts/models.ts +++ b/src/table/generated/artifacts/models.ts @@ -1407,12 +1407,12 @@ export type TableDeleteEntityResponse = TableDeleteEntityHeaders & { /** * Contains response data for the insertEntity operation. */ -export type TableInsertEntityResponse = { +export type TableInsertEntityResponse = TableInsertEntityHeaders & { /** - * The response body properties. + * The response body as a node.js Readable stream. */ - [propertyName: string]: any; -} & TableInsertEntityHeaders & { + body?: NodeJS.ReadableStream; +} & { /** * The response status code. */ diff --git a/src/table/generated/artifacts/specifications.ts b/src/table/generated/artifacts/specifications.ts index 7bce93104..dd98ebb2b 100644 --- a/src/table/generated/artifacts/specifications.ts +++ b/src/table/generated/artifacts/specifications.ts @@ -340,13 +340,9 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { responses: { 201: { bodyMapper: { + serializedName: "Stream", type: { - name: "Dictionary", - value: { - type: { - name: "Object" - } - } + name: "Stream" } }, headersMapper: Mappers.TableInsertEntityHeaders @@ -545,7 +541,7 @@ Specifications[Operation.Table_Create] = tableCreateOperationSpec; Specifications[Operation.Table_Delete] = tableDeleteOperationSpec; Specifications[Operation.Table_QueryEntities] = tableQueryEntitiesOperationSpec; Specifications[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = - tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; +tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; Specifications[Operation.Table_UpdateEntity] = tableUpdateEntityOperationSpec; Specifications[Operation.Table_MergeEntity] = tableMergeEntityOperationSpec; Specifications[Operation.Table_DeleteEntity] = tableDeleteEntityOperationSpec; diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index d19b793a2..276c21127 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -1,3 +1,4 @@ +import BufferStream from "../../common/utils/BufferStream"; import TableStorageContext from "../context/TableStorageContext"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; @@ -13,7 +14,7 @@ import { NO_METADATA_ACCEPT, RETURN_CONTENT, RETURN_NO_CONTENT, - TABLE_API_VERSION + TABLE_API_VERSION, } from "../utils/constants"; import { newEtag } from "../utils/utils"; import BaseHandler from "./BaseHandler"; @@ -34,7 +35,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { accept !== MINIMAL_METADATA_ACCEPT && accept !== FULL_METADATA_ACCEPT ) { - throw StorageErrorFactory.contentTypeNotSupported(context); + throw StorageErrorFactory.getContentTypeNotSupported(context); } if (accountName === undefined) { @@ -49,7 +50,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { const metadata = `${accountName}/$metadata#Tables/@Element`; const type = `${accountName}.Tables`; - const id = `Tables(${tableName})`; + const id = `${accountName}/Tables(${tableName})`; const editLink = `Tables(${tableName})`; const table: TableModel = { @@ -61,18 +62,30 @@ export default class TableHandler extends BaseHandler implements ITableHandler { odataeditLink: editLink }; - const statusCode = await this.metadataStore.createTable(context, table); + await this.metadataStore.createTable(context, table); + const response: Models.TableCreateResponse = { clientRequestId: options.requestId, requestId: tableCtx.contextID, version: TABLE_API_VERSION, date: context.startTime, - statusCode + statusCode: 204 }; + if (context.request!.getHeader("Prefer") === RETURN_NO_CONTENT) { + response.statusCode = 204; + response.preferenceApplied = RETURN_NO_CONTENT; + } + + if (context.request!.getHeader("Prefer") === RETURN_CONTENT) { + response.statusCode = 201; + response.preferenceApplied = "return-content"; + } + let protocol = "http"; let host = DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; + // TODO: Get host and port from Azurite Server instance if (tableCtx.request !== undefined) { host = tableCtx.request.getHeader("host") as string; protocol = tableCtx.request.getProtocol() as string; @@ -303,14 +316,16 @@ export default class TableHandler extends BaseHandler implements ITableHandler { !options.tableEntityProperties.PartitionKey || !options.tableEntityProperties.RowKey ) { - // TODO: Check error code and error message - throw new Error("Invalid entity"); + throw StorageErrorFactory.getPropertiesNeedValue(context); } - const entity: IEntity = options.tableEntityProperties as IEntity; - const eTag = newEtag(); - - entity.eTag = eTag; + const entity: IEntity = { + PartitionKey: options.tableEntityProperties.PartitionKey, + RowKey: options.tableEntityProperties.RowKey, + properties: options.tableEntityProperties, + lastModifiedTime: context.startTime!, + eTag: newEtag() + }; // TODO: Move logic to get host into utility methods let protocol = "http"; @@ -326,11 +341,6 @@ export default class TableHandler extends BaseHandler implements ITableHandler { const id = `${protocol}://${host}/Tables(${tableName})`; const editLink = `Tables(${tableName})`; - entity.metadata = metadata; - entity.type = type; - entity.id = id; - entity.editLink = editLink; - await this.metadataStore.insertTableEntity(context, tableName, entity); const response: Models.TableInsertEntityResponse = { @@ -349,10 +359,11 @@ export default class TableHandler extends BaseHandler implements ITableHandler { accept !== MINIMAL_METADATA_ACCEPT && accept !== FULL_METADATA_ACCEPT ) { - throw StorageErrorFactory.contentTypeNotSupported(context); + throw StorageErrorFactory.getContentTypeNotSupported(context); } response.contentType = "application/json"; + const body = {} as any; if (context.request!.getHeader("Prefer") === RETURN_NO_CONTENT) { response.statusCode = 204; @@ -364,21 +375,22 @@ export default class TableHandler extends BaseHandler implements ITableHandler { response.preferenceApplied = "return-content"; if (accept === MINIMAL_METADATA_ACCEPT) { - response["odata.metadata"] = metadata; + body["odata.metadata"] = metadata; } if (accept === FULL_METADATA_ACCEPT) { - response["odata.metadata"] = metadata; - response["odata.type"] = type; - response["odata.id"] = id; - response["odata.etag"] = eTag; - response["odata.editLink"] = editLink; + body["odata.metadata"] = metadata; + body["odata.type"] = type; + body["body.id"] = id; + body["odata.etag"] = entity.eTag; + body["odata.editLink"] = editLink; } - // TODO: Filter out non entity properties in response body (how about update swagger to response stream type?) - for (const key of Object.keys(entity)) { - response[key] = entity[key]; + for (const key of Object.keys(entity.properties)) { + body[key] = entity.properties[key]; } + + response.body = new BufferStream(Buffer.from(JSON.stringify(body))); } return response; } diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index 88c813061..87f7dca6e 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -1,6 +1,5 @@ import * as Models from "../generated/artifacts/models"; import Context from "../generated/Context"; -import { TABLE_STATUSCODE } from "../utils/constants"; // Since the host name may change, we don't store host in {@code odatametadata, odatatid} interface ITtableAdditionalProperties { @@ -16,15 +15,19 @@ interface ITtableAdditionalProperties { export interface IEntity { PartitionKey: string; RowKey: string; - [propertyName: string]: string | number; + eTag: string; + lastModifiedTime: Date; + properties: { + [propertyName: string]: string | number; + }; } export type TableModel = ITtableAdditionalProperties; export default interface ITableMetadataStore { queryTable(context: Context): Promise; - createTable(context: Context, table: TableModel): Promise; - deleteTable(context: Context, tableName: string): Promise; + createTable(context: Context, table: TableModel): Promise; + deleteTable(context: Context, tableName: string): Promise; queryTableEntities( context: Context, table: string, @@ -41,19 +44,19 @@ export default interface ITableMetadataStore { table: string, partitionKey: string, rowKey: string - ): Promise; + ): Promise; mergeTableEntity( context: Context, table: string, partitionKey: string, rowKey: string - ): Promise; + ): Promise; deleteTableEntity( context: Context, table: string, partitionKey: string, rowKey: string - ): Promise; + ): Promise; insertTableEntity( context: Context, tableName: string, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index 05c11dd90..f53fbc81f 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -6,7 +6,6 @@ import StorageErrorFactory from "../errors/StorageErrorFactory"; import * as Models from "../generated/artifacts/models"; import Context from "../generated/Context"; import { IEntity, TableModel } from "../persistence/ITableMetadataStore"; -import { TABLE_STATUSCODE } from "../utils/constants"; import ITableMetadataStore from "./ITableMetadataStore"; export default class LokiTableMetadataStore implements ITableMetadataStore { @@ -33,7 +32,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async createTable( context: Context, table: TableModel - ): Promise { + ): Promise { const coll = this.db.getCollection(this.TABLE_COLLECTION); const doc = coll.findOne({ accountName: table.account, @@ -49,7 +48,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { const extentColl = this.db.getCollection(table.tableName); if (extentColl) { - throw StorageErrorFactory.TableAlreadyExists(context); + throw StorageErrorFactory.getTableAlreadyExists(context); } this.db.addCollection(table.tableName, { @@ -57,8 +56,6 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { // https://rawgit.com/techfort/LokiJS/master/jsdoc/tutorial-Indexing%20and%20Query%20performance.html indices: ["ParititionKey", "RowKey"] }); // Optimize for find operation - - return 201; } public async insertTableEntity( @@ -68,21 +65,18 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { ): Promise { const tableColl = this.db.getCollection(tableName); if (!tableColl) { - throw StorageErrorFactory.TableNotExist(context); + throw StorageErrorFactory.getTableNotExist(context); } - // If the entity already exists in the table, throw an error const doc = tableColl.findOne({ - partitionKey: entity.partitionKey, - rowKey: entity.rowKey + PartitionKey: entity.PartitionKey, + RowKey: entity.RowKey }); if (doc) { - throw StorageErrorFactory.insertEntityAlreadyExist(context); + throw StorageErrorFactory.getEntityAlreadyExist(context); } - entity.lastModifiedTime = context.startTime!.toUTCString(); - tableColl.insert(entity); return; } @@ -97,7 +91,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async deleteTable( context: Context, tableName: string - ): Promise { + ): Promise { // TODO context: Context throw new NotImplementedError(); } @@ -126,7 +120,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { table: string, partitionKey: string, rowKey: string - ): Promise { + ): Promise { // TODO throw new NotImplementedError(); } @@ -136,7 +130,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { table: string, partitionKey: string, rowKey: string - ): Promise { + ): Promise { // TODO throw new NotImplementedError(); } @@ -146,7 +140,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { table: string, partitionKey: string, rowKey: string - ): Promise { + ): Promise { // TODO throw new NotImplementedError(); } diff --git a/swagger/table.md b/swagger/table.md index dc84619c1..8463bd77d 100644 --- a/swagger/table.md +++ b/swagger/table.md @@ -67,3 +67,16 @@ directive: }; $["TableResponse"]["allOf"] = undefined; ``` + +### Update Table_InsertEntity response to file + +```yaml +directive: + - from: swagger-document + where: $["paths"]["/{table}"].post.responses["201"] + transform: > + $.schema = { + "type": "object", + "format": "file" + }; +``` \ No newline at end of file diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index fca04e6f2..17a53a3f9 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -5,11 +5,7 @@ import { configLogger } from "../../../src/common/Logger"; import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; import { TABLE_API_VERSION } from "../../../src/table/utils/constants"; -import { - EMULATOR_ACCOUNT_KEY, - EMULATOR_ACCOUNT_NAME, - getUniqueName -} from "../../testutils"; +import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME, getUniqueName, overrideRequest } from "../../testutils"; // Set true to enable debug log configLogger(false); @@ -21,29 +17,73 @@ describe("table APIs test", () => { const port = 11002; const metadataDbPath = "__tableTestsStorage__"; - const config = new TableConfiguration(host, port, metadataDbPath, false); + const config = new TableConfiguration( + host, + port, + metadataDbPath, + false, + false + ); let server: TableServer; - const tableName: string = getUniqueName("table"); const accountName = EMULATOR_ACCOUNT_NAME; const sharedKey = EMULATOR_ACCOUNT_KEY; const connectionString = `DefaultEndpointsProtocol=${protocol};AccountName=${accountName};` + `AccountKey=${sharedKey};TableEndpoint=${protocol}://${host}:${port}/${accountName};`; + const tableService = Azure.createTableService(connectionString); + + let tableName: string = getUniqueName("table"); + + const requestOverride = { headers: {} }; + overrideRequest(requestOverride, tableService); + before(async () => { server = new TableServer(config); + tableName = getUniqueName("table"); await server.start(); }); - it("createTable @loki", done => { - /* TODO: Azure Storage Table SDK doesn't support customize Accept header, - thus we cannot test following 3 OData levels and respones. + after(async () => { + await server.close(); + }); + + it("createTable, prefer=return-no-content, accept=application/json;odata=minimalmetadata @loki", done => { + /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, + thus we workaround this by override request headers to test following 3 OData levels responses. + - application/json;odata=nometadata + - application/json;odata=minimalmetadata + - application/json;odata=fullmetadata + */ + requestOverride.headers = { + Prefer: "return-no-content", + accept: "application/json;odata=minimalmetadata" + }; + + tableService.createTable(tableName, (error, result, response) => { + if (!error) { + assert.equal(result.TableName, tableName); + assert.equal(result.statusCode, 204); + const headers = response.headers!; + assert.equal(headers["x-ms-version"], TABLE_API_VERSION); + assert.deepStrictEqual(response.body, ""); + } + done(); + }); + }); + + it("createTable, prefer=return-content, accept=application/json;odata=fullmetadata @loki", done => { + /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, + thus we workaround this by override request headers to test following 3 OData levels responses. - application/json;odata=nometadata - application/json;odata=minimalmetadata - application/json;odata=fullmetadata */ - const tableService = Azure.createTableService(connectionString); + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; tableService.createTable(tableName, (error, result, response) => { if (!error) { @@ -51,12 +91,33 @@ describe("table APIs test", () => { assert.equal(result.statusCode, 201); const headers = response.headers!; assert.equal(headers["x-ms-version"], TABLE_API_VERSION); + const bodies = response.body! as any; + assert.deepStrictEqual(bodies.TableName, tableName); + assert.deepStrictEqual(bodies["odata.type"], `${accountName}.Tables`); + assert.deepStrictEqual( + bodies["odata.metadata"], + `${protocol}://${host}:${port}/${accountName}/$metadata#Tables/@Element` + ); + assert.deepStrictEqual( + bodies["odata.id"], + `${protocol}://${host}:${port}/${accountName}/Tables(${tableName})` + ); + assert.deepStrictEqual( + bodies["odata.editLink"], + `Tables(${tableName})` + ); } done(); }); }); - after(async () => { - await server.close(); + it("createTable, prefer=return-content, accept=application/json;odata=minimalmetadata @loki", done => { + // TODO + done(); + }); + + it("createTable, prefer=return-content, accept=application/json;odata=nometadata @loki", done => { + // TODO + done(); }); }); diff --git a/tests/testutils.ts b/tests/testutils.ts index bb03b6dba..903e12541 100644 --- a/tests/testutils.ts +++ b/tests/testutils.ts @@ -1,3 +1,4 @@ +import { StorageServiceClient } from "azure-storage"; import { randomBytes } from "crypto"; import { createWriteStream, readFileSync } from "fs"; import { sign } from "jsonwebtoken"; @@ -198,3 +199,36 @@ export function generateJWTToken( ); return token; } + +export function overrideRequest( + override: { + headers: { [key: string]: string }; + } = { headers: {} }, + serivce: StorageServiceClient +) { + const _buildRequestOptions = (serivce as any).__proto__.__proto__._buildRequestOptions.bind( + serivce + ); + (serivce as any).__proto__.__proto__._buildRequestOptions = ( + webResource: any, + body: any, + options: any, + callback: any + ) => { + _buildRequestOptions( + webResource, + body, + options, + (err: any, finalRequestOptions: any) => { + for (const key in override.headers) { + if (Object.prototype.hasOwnProperty.call(override.headers, key)) { + const element = override.headers[key]; + finalRequestOptions.headers[key] = element; + } + } + + callback(err, finalRequestOptions); + } + ); + }; +} From c75c065a9e3bcff33b3387075b00b65f9e7659bd Mon Sep 17 00:00:00 2001 From: Takekazu Omi Date: Tue, 28 Jul 2020 13:54:30 +0900 Subject: [PATCH 06/57] Update Dockerfile for table support. (#522) * update Dockerfile for table support. https://github.com/Azure/Azurite/issues/510 * add missing space after '-p' * add azurite-table entry. --- Dockerfile | 4 +++- README.mcr.md | 17 +++++++++++------ README.md | 27 ++++++++++++++++----------- azure-pipelines.yml | 1 + 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index a875ec812..8b3655a6b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,5 +21,7 @@ RUN npm install -g --loglevel verbose EXPOSE 10000 # Queue Storage Port EXPOSE 10001 +# Table Storage Port +EXPOSE 10002 -CMD ["azurite", "-l", "/data", "--blobHost", "0.0.0.0","--queueHost", "0.0.0.0"] \ No newline at end of file +CMD ["azurite", "-l", "/data", "--blobHost", "0.0.0.0","--queueHost", "0.0.0.0", "--tableHost", "0.0.0.0"] \ No newline at end of file diff --git a/README.mcr.md b/README.mcr.md index 7579f0d6d..49b5c964b 100644 --- a/README.mcr.md +++ b/README.mcr.md @@ -17,11 +17,12 @@ Azurite is an open source Azure Storage API compatible server (emulator). Based # How to Use this Image ```bash -docker run -p 10000:10000 -p 10001:10001 mcr.microsoft.com/azure-storage/azurite +docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azurite ``` -`-p 10000:10000` will expose blob service's default listening port. +`-p 10000:10000` will expose blob service's default listening port. `-p 10001:10001` will expose queue service's default listening port. +`-p 10002:10002` will expose table service's default listening port. Just run blob service: @@ -32,7 +33,7 @@ docker run -p 10000:10000 mcr.microsoft.com/azure-storage/azurite azurite-blob - **Run Azurite V3 docker image with customized persisted data location** ```bash -docker run -p 10000:10000 -p 10001:10001 -v c:/azurite:/data mcr.microsoft.com/azure-storage/azurite +docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 -v c:/azurite:/data mcr.microsoft.com/azure-storage/azurite ``` `-v c:/azurite:/data` will use and map host path `c:/azurite` as Azurite's workspace location. @@ -40,7 +41,7 @@ docker run -p 10000:10000 -p 10001:10001 -v c:/azurite:/data mcr.microsoft.com/a **Customize Azurite V3 supported parameters for docker image** ```bash -docker run -p 8888:8888 -p 9999:9999 -v c:/azurite:/workspace mcr.microsoft.com/azure-storage/azurite azurite -l /workspace -d /workspace/debug.log --blobPort 8888 --blobHost 0.0.0.0 --queuePort 9999 --queueHost 0.0.0.0 --loose --skipApiVersionCheck +docker run -p 7777:7777 -p 8888:8888 -p 9999:9999 -v c:/azurite:/workspace mcr.microsoft.com/azure-storage/azurite azurite -l /workspace -d /workspace/debug.log --blobPort 7777 --blobHost 0.0.0.0 --queuePort 8888 --queueHost 0.0.0.0 --tablePort 9999 --tableHost 0.0.0.0 --loose --skipApiVersionCheck ``` Above command will try to start Azurite image with configurations: @@ -49,14 +50,18 @@ Above command will try to start Azurite image with configurations: `-d //workspace/debug.log` enables debug log into `/workspace/debug.log` inside docker instance. `debug.log` will also mapped to `c:/azurite/debug.log` in host machine because of docker volume mapping. -`--blobPort 8888` makes Azurite blob service listen to port 8888, while `-p 8888:8888` redirects requests from host machine's port 8888 to docker instance. +`--blobPort 7777` makes Azurite blob service listen to port 7777, while `-p 7777:7777` redirects requests from host machine's port 7777 to docker instance. `--blobHost 0.0.0.0` defines blob service listening endpoint to accept requests from host machine. -`--queuePort 9999` makes Azurite queue service listen to port 9999, while `-p 9999:9999` redirects requests from host machine's port 9999 to docker instance. +`--queuePort 8888` makes Azurite queue service listen to port 8888, while `-p 8888:8888` redirects requests from host machine's port 8888 to docker instance. `--queueHost 0.0.0.0` defines queue service listening endpoint to accept requests from host machine. +`--tablePort 9999` makes Azurite table service listen to port 9999, while `-p 9999:9999` redirects requests from host machine's port 9999 to docker instance. + +`--tableHost 0.0.0.0` defines table service listening endpoint to accept requests from host machine. + `--loose` enables loose mode which ignore unsupported headers and parameters. `--skipApiVersionCheck` skip the request API version check. diff --git a/README.md b/README.md index 88100f4c9..4130d2e6e 100644 --- a/README.md +++ b/README.md @@ -138,11 +138,12 @@ Following extension configurations are supported: > Note. Find more docker images tags in https://mcr.microsoft.com/v2/azure-storage/azurite/tags/list ```bash -docker run -p 10000:10000 -p 10001:10001 mcr.microsoft.com/azure-storage/azurite +docker run -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azure-storage/azurite ``` `-p 10000:10000` will expose blob service's default listening port. `-p 10001:10001` will expose queue service's default listening port. +`-p 10002:10002` will expose table service's default listening port. Or just run blob service: @@ -161,7 +162,7 @@ docker run -p 10000:10000 -p 10001:10001 -v c:/azurite:/data mcr.microsoft.com/a #### Customize all Azurite V3 supported parameters for docker image ```bash -docker run -p 8888:8888 -p 9999:9999 -v c:/azurite:/workspace mcr.microsoft.com/azure-storage/azurite azurite -l /workspace -d /workspace/debug.log --blobPort 8888 --blobHost 0.0.0.0 --queuePort 9999 --queueHost 0.0.0.0 --loose --skipApiVersionCheck +docker run -p 7777:7777 -p 8888:8888 -p 9999:9999 -v c:/azurite:/workspace mcr.microsoft.com/azure-storage/azurite azurite -l /workspace -d /workspace/debug.log --blobPort 7777 --blobHost 0.0.0.0 --queuePort 8888 --queueHost 0.0.0.0 --tablePort 9999 --tableHost 0.0.0.0 --loose --skipApiVersionCheck ``` Above command will try to start Azurite image with configurations: @@ -170,14 +171,18 @@ Above command will try to start Azurite image with configurations: `-d //workspace/debug.log` enables debug log into `/workspace/debug.log` inside docker instance. `debug.log` will also mapped to `c:/azurite/debug.log` in host machine because of docker volume mapping. -`--blobPort 8888` makes Azurite blob service listen to port 8888, while `-p 8888:8888` redirects requests from host machine's port 8888 to docker instance. +`--blobPort 7777` makes Azurite blob service listen to port 7777, while `-p 7777:7777` redirects requests from host machine's port 7777 to docker instance. `--blobHost 0.0.0.0` defines blob service listening endpoint to accept requests from host machine. -`--queuePort 9999` makes Azurite queue service listen to port 9999, while `-p 9999:9999` redirects requests from host machine's port 9999 to docker instance. +`--queuePort 8888` makes Azurite queue service listen to port 8888, while `-p 8888:8888` redirects requests from host machine's port 8888 to docker instance. `--queueHost 0.0.0.0` defines queue service listening endpoint to accept requests from host machine. +`--tablePort 9999` makes Azurite table service listen to port 9999, while `-p 9999:9999` redirects requests from host machine's port 9999 to docker instance. + +`--tableHost 0.0.0.0` defines table service listening endpoint to accept requests from host machine. + `--loose` enables loose mode which ignore unsupported headers and parameters. `--skipApiVersionCheck` skip the request API version check. @@ -260,7 +265,7 @@ Optional. By default Azurite will display access log in console. **Disable** it ### Debug Log Configuration -Optional. Debug log includes detailed information on every request and exception stack traces. +Optional. Debug log includes detailed information on every request and exception stack traces. Enable it by providing a valid local file path for the debug log destination. ```cmd @@ -752,7 +757,7 @@ Azurite V3 selected TypeScript as its' programming language, as this facilitates ### Features Scope -Legacy Azurite V2 supports Azure Storage Blob, Queue and Table services. +Legacy Azurite V2 supports Azure Storage Blob, Queue and Table services. Azurite V3 currently only supports Azure Storage blob service. Queue service is supported after V3.2.0-preview. Table service support is currently under discussion. @@ -760,14 +765,14 @@ Azurite V3 supports features from Azure Storage API version 2019-12-12, and will ## TypeScript Server Code Generator -Azurite V3 leverages a TypeScript Node.js Server Code Generator to generate the majority of code from Azure Storage REST APIs swagger specification. +Azurite V3 leverages a TypeScript Node.js Server Code Generator to generate the majority of code from Azure Storage REST APIs swagger specification. Currently, the generator project is private, under development and only used by Azurite V3. -We have plans to make the TypeScript server generator public after Azurite V3 releases. +We have plans to make the TypeScript server generator public after Azurite V3 releases. All the generated code is kept in `generated` folder, including the generated middleware, request and response models. ## Support Matrix -Latest release targets **2019-12-12** API version **blob** service. +Latest release targets **2019-12-12** API version **blob** service. Detailed support matrix: - Supported Vertical Features @@ -852,8 +857,8 @@ This project is licensed under MIT. > Go to [GitHub project](https://github.com/Azure/Azurite/projects) page or [GitHub issues](https://github.com/Azure/Azurite/issues) for the milestone and TODO items we are used for tracking upcoming features and bug fixes. -We are currently working on Azurite V3 to implement the remaining Azure Storage REST APIs. -We finished the basic structure and majority of features in Blob Storage, as can be seen in the support matrix. +We are currently working on Azurite V3 to implement the remaining Azure Storage REST APIs. +We finished the basic structure and majority of features in Blob Storage, as can be seen in the support matrix. The detailed work items are also tracked in GitHub repository projects and issues. Any contribution and suggestions for Azurite V3 is welcome, please goto [CONTRIBUTION.md](https://github.com/Azure/Azurite/blob/master/CONTRIBUTION.md) for detailed contribution guidelines. Alternatively, you can open GitHub issues voting for any missing features in Azurite V3. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e5f01163b..5787e5ab3 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -470,6 +470,7 @@ jobs: docker run xstoreazurite.azurecr.io/public/azure-storage/azurite:latest azurite -v docker run xstoreazurite.azurecr.io/public/azure-storage/azurite:latest azurite-blob -v docker run xstoreazurite.azurecr.io/public/azure-storage/azurite:latest azurite-queue -v + docker run xstoreazurite.azurecr.io/public/azure-storage/azurite:latest azurite-table -v workingDirectory: "./" displayName: "Validate docker image" From c5732329a008321bbbf9776c0cc2175c000fc091 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Wed, 29 Jul 2020 15:34:21 +0200 Subject: [PATCH 07/57] DeleteTable Implementation (#524) * quick and dirty delete table implementation, needs improving! * Delete Table Implementation & tests * forgot to remove comment and only designation on test * updated persistence layer - create to also use the account table name concatenation * Updated based on Xiaonings review. --- .gitignore | 1 + src/table/errors/StorageErrorFactory.ts | 11 ++++ src/table/handlers/TableHandler.ts | 39 ++++++++----- src/table/persistence/ITableMetadataStore.ts | 7 ++- .../persistence/LokiTableMetadataStore.ts | 57 +++++++++++++++---- tests/table/apis/table.test.ts | 49 +++++++++++++++- 6 files changed, 135 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 7db1cbad8..9d9bd1585 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ __* *.env temp **/.DS_Store.DS_Store +*.pem \ No newline at end of file diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 928bb947e..90352f331 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -86,4 +86,15 @@ export default class StorageErrorFactory { context ); } + + public static getTableNotFound(context: Context): StorageError { + return new StorageError( + 404, + "TableNotFound", + "The table specified does not exist.", + context.contextID || defaultID, + undefined, + context + ); + } } diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 276c21127..6feda962f 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -14,7 +14,7 @@ import { NO_METADATA_ACCEPT, RETURN_CONTENT, RETURN_NO_CONTENT, - TABLE_API_VERSION, + TABLE_API_VERSION } from "../utils/constants"; import { newEtag } from "../utils/utils"; import BaseHandler from "./BaseHandler"; @@ -138,23 +138,27 @@ export default class TableHandler extends BaseHandler implements ITableHandler { } public async delete( - table: string, + tablename: string, options: Models.TableDeleteMethodOptionalParams, context: Context ): Promise { - // e.g - // const tableCtx = new TableStorageContext(context); - // const accountName = tableCtx.account; - // const tableName = tableCtx.tableName; // Get tableName from context - // return { - // statusCode: 204, - // clientRequestId: "clientRequestId", - // requestId: "requestId", - // version: "version" - // }; + const tableCtx = new TableStorageContext(context); + const accountName = tableCtx.account; + // currently the tableName is not coming through, so we take it from the table context + await this.metadataStore.deleteTable( + context, + tableCtx.tableName!, + accountName! + ); + const response: Models.TableDeleteResponse = { + clientRequestId: options.requestId, + requestId: tableCtx.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode: 204 + }; - // TODO - throw new NotImplementedError(); + return response; } public async queryEntities( @@ -341,7 +345,12 @@ export default class TableHandler extends BaseHandler implements ITableHandler { const id = `${protocol}://${host}/Tables(${tableName})`; const editLink = `Tables(${tableName})`; - await this.metadataStore.insertTableEntity(context, tableName, entity); + await this.metadataStore.insertTableEntity( + context, + tableName, + accountName!, + entity + ); const response: Models.TableInsertEntityResponse = { clientRequestId: options.requestId, diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index 87f7dca6e..ff504a41a 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -27,7 +27,11 @@ export type TableModel = ITtableAdditionalProperties; export default interface ITableMetadataStore { queryTable(context: Context): Promise; createTable(context: Context, table: TableModel): Promise; - deleteTable(context: Context, tableName: string): Promise; + deleteTable( + context: Context, + tableName: string, + accountName: string + ): Promise; queryTableEntities( context: Context, table: string, @@ -60,6 +64,7 @@ export default interface ITableMetadataStore { insertTableEntity( context: Context, tableName: string, + account: string, entity: IEntity ): Promise; getTableAccessPolicy( diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index f53fbc81f..bbcb37237 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -29,13 +29,11 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { return this.closed; } - public async createTable( - context: Context, - table: TableModel - ): Promise { + public async createTable(context: Context, table: TableModel): Promise { + // Check for table entry in the table registry collection const coll = this.db.getCollection(this.TABLE_COLLECTION); const doc = coll.findOne({ - accountName: table.account, + account: table.account, name: table.tableName }); @@ -43,15 +41,19 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { if (doc) { throw StorageErrorFactory.getTableAlreadyExists(context); } - coll.insert(table); - const extentColl = this.db.getCollection(table.tableName); + // now we create the collection to represent the table using a unique string + const uniqueTableName = this.getUniqueTableCollectionName( + table.account, + table.tableName + ); + const extentColl = this.db.getCollection(uniqueTableName); if (extentColl) { throw StorageErrorFactory.getTableAlreadyExists(context); } - this.db.addCollection(table.tableName, { + this.db.addCollection(uniqueTableName, { // Optimization for indexing and searching // https://rawgit.com/techfort/LokiJS/master/jsdoc/tutorial-Indexing%20and%20Query%20performance.html indices: ["ParititionKey", "RowKey"] @@ -61,9 +63,12 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async insertTableEntity( context: Context, tableName: string, + account: string, entity: IEntity ): Promise { - const tableColl = this.db.getCollection(tableName); + const tableColl = this.db.getCollection( + this.getUniqueTableCollectionName(account, tableName) + ); if (!tableColl) { throw StorageErrorFactory.getTableNotExist(context); } @@ -90,10 +95,31 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async deleteTable( context: Context, - tableName: string + name: string, + accountName: string ): Promise { - // TODO context: Context - throw new NotImplementedError(); + const uniqueTableName = this.getUniqueTableCollectionName( + accountName, + name + ); + const tableColl = this.db.getCollection(uniqueTableName); + // delete the collection / table + if (tableColl != null) { + this.db.removeCollection(uniqueTableName); + } else { + throw StorageErrorFactory.getTableNotFound(context); + } + // remove table reference from collection registry + const coll = this.db.getCollection(this.TABLE_COLLECTION); + const doc = coll.findOne({ + account: accountName, + tableName: name + }); + if (doc != null) { + coll.remove(doc); + } else { + throw StorageErrorFactory.getTableNotFound(context); + } } public async queryTableEntities( @@ -215,4 +241,11 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { this.closed = true; } + + private getUniqueTableCollectionName( + accountName: string, + tableName: string + ): string { + return `${accountName}$${tableName}`; + } } diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index 17a53a3f9..9e03edfe1 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -5,7 +5,12 @@ import { configLogger } from "../../../src/common/Logger"; import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; import { TABLE_API_VERSION } from "../../../src/table/utils/constants"; -import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME, getUniqueName, overrideRequest } from "../../testutils"; +import { + EMULATOR_ACCOUNT_KEY, + EMULATOR_ACCOUNT_NAME, + getUniqueName, + overrideRequest +} from "../../testutils"; // Set true to enable debug log configLogger(false); @@ -120,4 +125,46 @@ describe("table APIs test", () => { // TODO done(); }); + + it("deleteTable that exists, @loki", done => { + /* + https://docs.microsoft.com/en-us/rest/api/storageservices/delete-table + */ + requestOverride.headers = {}; + + const tableToDelete = tableName + "del"; + + tableService.createTable(tableToDelete, (error, result, response) => { + if (!error) { + tableService.deleteTable(tableToDelete, (deleteError, deleteResult) => { + if (!deleteError) { + // no body expected, we expect 204 no content on successful deletion + assert.equal(deleteResult.statusCode, 204); + } else { + assert.ifError(deleteError); + } + done(); + }); + } else { + assert.fail("Test failed to create the table"); + done(); + } + }); + }); + + it("deleteTable that does not exist, @loki", done => { + /* + https://docs.microsoft.com/en-us/rest/api/storageservices/delete-table + */ + requestOverride.headers = {}; + + const tableToDelete = tableName + "causeerror"; + + tableService.deleteTable(tableToDelete, (error, result) => { + assert.equal(result.statusCode, 404); // no body expected, we expect 404 + const storageError = error as any; + assert.equal(storageError.code, "TableNotFound"); + done(); + }); + }); }); From 45b2ce0aa370d1838da462f794d0b90ac693a7af Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Thu, 30 Jul 2020 09:45:18 +0200 Subject: [PATCH 08/57] Table delete entity (#525) * quick and dirty delete table implementation, needs improving! * Delete Table Implementation & tests * forgot to remove comment and only designation on test * updated persistence layer - create to also use the account table name concatenation * Updated based on Xiaonings review. * delete entity implemented * delete entity implementation * updating as per PR comments * updated tslint rule to false for object-literal-key-quotes * Update table.entity.test.ts Co-authored-by: xiaonlimsft --- src/table/errors/StorageErrorFactory.ts | 22 +++ src/table/handlers/TableHandler.ts | 43 +++-- src/table/persistence/ITableMetadataStore.ts | 6 +- .../persistence/LokiTableMetadataStore.ts | 33 +++- tests/table/apis/table.entity.test.ts | 181 ++++++++++++++++++ tests/table/apis/table.test.ts | 4 +- tslint.json | 1 + 7 files changed, 266 insertions(+), 24 deletions(-) create mode 100644 tests/table/apis/table.entity.test.ts diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 90352f331..27914df5a 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -97,4 +97,26 @@ export default class StorageErrorFactory { context ); } + + public static getEntityNotFound(context: Context): StorageError { + return new StorageError( + 404, + "EntityNotFound", + "The specified entity does not exist.", + context.contextID || defaultID, + undefined, + context + ); + } + + public static getPreconditionFailed(context: Context): StorageError { + return new StorageError( + 412, + "UpdateConditionNotSatisfied", + "The update condition specified in the request was not satisfied.", + context.contextID || defaultID, + undefined, + context + ); + } } diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 6feda962f..e34972bdb 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -289,21 +289,34 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableDeleteEntityOptionalParams, context: Context ): Promise { - // e.g - // const tableCtx = new TableStorageContext(context); - // const accountName = tableCtx.account; - // const tableName = tableCtx.tableName; // Get tableName from context - // const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context - // const rowKey = tableCtx.rowKey!; // Get rowKey from context - // return { - // statusCode: 204, - // date: tableCtx.startTime, - // clientRequestId: "clientRequestId", - // requestId: "requestId", - // version: "version" - // }; - // TODO - throw new NotImplementedError(); + const tableCtx = new TableStorageContext(context); + const accountName = tableCtx.account; + const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context + const rowKey = tableCtx.rowKey!; // Get rowKey from context + + if (!partitionKey || !rowKey) { + throw StorageErrorFactory.getPropertiesNeedValue(context); + } + if (ifMatch === "" || ifMatch === undefined) { + throw StorageErrorFactory.getPreconditionFailed(context); + } + // currently the props are not coming through as args, so we take them from the table context + await this.metadataStore.deleteTableEntity( + context, + tableCtx.tableName!, + accountName!, + partitionKey, + rowKey, + ifMatch + ); + + return { + statusCode: 204, + date: tableCtx.startTime, + clientRequestId: options.requestId, + requestId: tableCtx.contextID, + version: TABLE_API_VERSION + }; } public async insertEntity( diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index ff504a41a..656c381d0 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -57,9 +57,11 @@ export default interface ITableMetadataStore { ): Promise; deleteTableEntity( context: Context, - table: string, + tableName: string, + accountName: string, partitionKey: string, - rowKey: string + rowKey: string, + eatg: string ): Promise; insertTableEntity( context: Context, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index bbcb37237..549fc49e0 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -163,12 +163,37 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async deleteTableEntity( context: Context, - table: string, + tableName: string, + accountName: string, partitionKey: string, - rowKey: string + rowKey: string, + etag: string ): Promise { - // TODO - throw new NotImplementedError(); + const tableColl = this.db.getCollection( + this.getUniqueTableCollectionName(accountName, tableName) + ); + if (!tableColl) { + throw StorageErrorFactory.getTableNotExist(context); + } + + if (partitionKey !== undefined && rowKey !== undefined) { + const doc = tableColl.findOne({ + PartitionKey: partitionKey, + RowKey: rowKey + }) as IEntity; + + if (!doc) { + throw StorageErrorFactory.getEntityNotFound(context); + } else { + if (etag !== "*" && doc.eTag !== etag) { + throw StorageErrorFactory.getPreconditionFailed(context); + } + } + tableColl.remove(doc); + return; + } + + throw StorageErrorFactory.getPropertiesNeedValue(context); } public async getTableAccessPolicy( diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts new file mode 100644 index 000000000..1c83cf9a9 --- /dev/null +++ b/tests/table/apis/table.entity.test.ts @@ -0,0 +1,181 @@ +import * as assert from "assert"; +import * as Azure from "azure-storage"; + +import { configLogger } from "../../../src/common/Logger"; +import TableConfiguration from "../../../src/table/TableConfiguration"; +import TableServer from "../../../src/table/TableServer"; +import { + EMULATOR_ACCOUNT_KEY, + EMULATOR_ACCOUNT_NAME, + getUniqueName, + overrideRequest +} from "../../testutils"; + +// Set true to enable debug log +configLogger(false); + +describe("table Entity APIs test", () => { + // TODO: Create a server factory as tests utils + const protocol = "http"; + const host = "127.0.0.1"; + const port = 11002; + const metadataDbPath = "__tableTestsStorage__"; + + const config = new TableConfiguration( + host, + port, + metadataDbPath, + false, + false + ); + + let server: TableServer; + const accountName = EMULATOR_ACCOUNT_NAME; + const sharedKey = EMULATOR_ACCOUNT_KEY; + const connectionString = + `DefaultEndpointsProtocol=${protocol};AccountName=${accountName};` + + `AccountKey=${sharedKey};TableEndpoint=${protocol}://${host}:${port}/${accountName};`; + + const tableService = Azure.createTableService(connectionString); + + let tableName: string = getUniqueName("table"); + + const requestOverride = { headers: {} }; + overrideRequest(requestOverride, tableService); + + before(async () => { + server = new TableServer(config); + tableName = getUniqueName("table"); + await server.start(); + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + + tableService.createTable(tableName, (error, result, response) => { + // created table for tests + }); + }); + + after(async () => { + await server.close(); + }); + + // Simple test in here until we have the full set checked in, as we need + // a starting point for delete and query entity APIs + it("Should insert new Entity, @loki", done => { + // https://docs.microsoft.com/en-us/rest/api/storageservices/insert-entity + const entity = { + PartitionKey: "part1", + RowKey: "row1", + myValue: "value1" + }; + tableService.insertEntity(tableName, entity, (error, result, response) => { + assert.equal(response.statusCode, 201); + done(); + }); + }); + + it("Should delete an Entity using etag wildcard, @loki", done => { + // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1 + const entity = { + PartitionKey: "part1", + RowKey: "row1", + myValue: "somevalue", + ".metadata": { + etag: "*" // forcing unconditional etag match to delete + } + }; + + /* https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1#request-headers + If-Match Required. The client may specify the ETag for the entity on the request in + order to compare to the ETag maintained by the service for the purpose of optimistic concurrency. + The delete operation will be performed only if the ETag sent by the client matches the value + maintained by the server, indicating that the entity has not been modified since it was retrieved by the client. + To force an unconditional delete, set If-Match to the wildcard character (*). */ + + tableService.deleteEntity(tableName, entity, (error, response) => { + assert.equal(response.statusCode, 204); + done(); + }); + }); + + it("Should not delete an Entity not matching Etag, @loki", done => { + // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1 + const entityInsert = { + PartitionKey: "part1", + RowKey: "row2", + myValue: "shouldNotMatchetag" + }; + const entityDelete = { + PartitionKey: "part1", + RowKey: "row2", + myValue: "shouldNotMatchetag", + ".metadata": { + etag: "0x2252C97588D4000" + } + }; + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + tableService.insertEntity( + tableName, + entityInsert, + (insertError, insertResult, insertResponse) => { + if (!insertError) { + requestOverride.headers = {}; + tableService.deleteEntity( + tableName, + entityDelete, + (deleteError, deleteResponse) => { + assert.equal(deleteResponse.statusCode, 412); // Precondition failed + done(); + } + ); + } else { + assert.ifError(insertError); + done(); + } + } + ); + }); + + it("Should delete a matching Etag, @loki", done => { + // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1 + const entityInsert = { + PartitionKey: "part1", + RowKey: "row3", + myValue: "shouldMatchEtag" + }; + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + tableService.insertEntity( + tableName, + entityInsert, + (error, result, insertresponse) => { + if (!error) { + requestOverride.headers = {}; + tableService.deleteEntity( + tableName, + result, // SDK defined entity type... + (deleteError, deleteResponse) => { + if (!deleteError) { + assert.equal(deleteResponse.statusCode, 204); // Precondition succeeded + done(); + } else { + assert.ifError(deleteError); + done(); + } + } + ); + } else { + assert.ifError(error); + done(); + } + } + ); + }); +}); diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index 9e03edfe1..4f632177d 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -153,9 +153,7 @@ describe("table APIs test", () => { }); it("deleteTable that does not exist, @loki", done => { - /* - https://docs.microsoft.com/en-us/rest/api/storageservices/delete-table - */ + // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-table requestOverride.headers = {}; const tableToDelete = tableName + "causeerror"; diff --git a/tslint.json b/tslint.json index c5f9e71d8..74f2dd55b 100644 --- a/tslint.json +++ b/tslint.json @@ -7,6 +7,7 @@ "arrow-parens": false, "variable-name": false, "object-literal-sort-keys": false, + "object-literal-key-quotes": false, "array-type": false }, "rulesDirectory": [], From 19b753ce254732a4f7581a80d8d3f29e8c1d5261 Mon Sep 17 00:00:00 2001 From: Sonja Goerlich <61382168+sonniiy@users.noreply.github.com> Date: Fri, 7 Aug 2020 05:59:55 +0200 Subject: [PATCH 09/57] Add update Entity feature (#528) * First implementation on Handler side * Added Metadata Layer for update function * Corrected path to package.json so that test file works * Added functional test cases * Added the logic to test if the eTag has changed * Added tests for etags * Added code descriptions * Changed order of remove and insert and fixed typo Co-authored-by: Sonja Goerlich --- package.json | 2 +- src/table/errors/StorageErrorFactory.ts | 13 +- src/table/generated/handlers/ITableHandler.ts | 74 ++++++++-- src/table/handlers/TableHandler.ts | 64 ++++++-- src/table/persistence/ITableMetadataStore.ts | 7 +- .../persistence/LokiTableMetadataStore.ts | 38 ++++- tests/table/apis/table.entity.test.ts | 138 ++++++++++++++++++ 7 files changed, 298 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 825acd66f..a87eafff7 100644 --- a/package.json +++ b/package.json @@ -228,7 +228,7 @@ "test:blob:sql": "npm run lint && cross-env cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 AZURITE_TEST_DB=mysql://root:my-secret-pw@127.0.0.1:3306/azurite_blob_test mocha --compilers ts-node/register --no-timeouts --grep @sql --recursive tests/blob/*.test.ts tests/blob/**/*.test.ts", "test:blob:sql:ci": "npm run lint && cross-env cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 AZURITE_TEST_DB=mysql://root:my-secret-pw@127.0.0.1:13306/azurite_blob_test mocha --compilers ts-node/register --no-timeouts --grep @sql --recursive tests/blob/*.test.ts tests/blob/**/*.test.ts", "test:queue": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/queue/*.test.ts tests/queue/**/*.test.ts", - "test:table": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/table/*.test.ts tests/table/**/*.test.ts", + "test:table": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/table/apis/*.test.ts tests/table/apis/**/*.test.ts", "clean": "rimraf dist typings *.log coverage __testspersistence__ temp __testsstorage__ .nyc_output debug.log *.vsix *.tgz", "clean:deep": "npm run clean && rimraf debug.log __*", "validate:npmpack:win": "npm install && npm run build && npm pack && cross-var npm install -g azurite-$npm_package_version.tgz && azurite -v && azurite-blob -v && azurite-queue -v", diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 27914df5a..4e49b8432 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -47,7 +47,18 @@ export default class StorageErrorFactory { return new StorageError( 400, "AccountNameEmpty", - "The table to insert doesn't exist", + "The table you want to manipulate doesn't exist", + context.contextID || defaultID, + undefined, + context + ); + } + + public static getEntityNotExist(context: Context): StorageError { + return new StorageError( + 409, + "EntityDoesNotExist", + "The entity to update doesn't exist in the table", context.contextID || defaultID, undefined, context diff --git a/src/table/generated/handlers/ITableHandler.ts b/src/table/generated/handlers/ITableHandler.ts index ce47d37dd..9237f6d5c 100644 --- a/src/table/generated/handlers/ITableHandler.ts +++ b/src/table/generated/handlers/ITableHandler.ts @@ -13,15 +13,67 @@ import * as Models from "../artifacts/models"; import Context from "../Context"; export default interface ITableHandler { - query(options: Models.TableQueryOptionalParams, context: Context): Promise; - create(tableProperties: Models.TableProperties, options: Models.TableCreateOptionalParams, context: Context): Promise; - delete(table: string, options: Models.TableDeleteMethodOptionalParams, context: Context): Promise; - queryEntities(table: string, options: Models.TableQueryEntitiesOptionalParams, context: Context): Promise; - queryEntitiesWithPartitionAndRowKey(table: string, partitionKey: string, rowKey: string, options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, context: Context): Promise; - updateEntity(table: string, partitionKey: string, rowKey: string, options: Models.TableUpdateEntityOptionalParams, context: Context): Promise; - mergeEntity(table: string, partitionKey: string, rowKey: string, options: Models.TableMergeEntityOptionalParams, context: Context): Promise; - deleteEntity(table: string, partitionKey: string, rowKey: string, ifMatch: string, options: Models.TableDeleteEntityOptionalParams, context: Context): Promise; - insertEntity(table: string, options: Models.TableInsertEntityOptionalParams, context: Context): Promise; - getAccessPolicy(table: string, options: Models.TableGetAccessPolicyOptionalParams, context: Context): Promise; - setAccessPolicy(table: string, options: Models.TableSetAccessPolicyOptionalParams, context: Context): Promise; + query( + options: Models.TableQueryOptionalParams, + context: Context + ): Promise; + create( + tableProperties: Models.TableProperties, + options: Models.TableCreateOptionalParams, + context: Context + ): Promise; + delete( + table: string, + options: Models.TableDeleteMethodOptionalParams, + context: Context + ): Promise; + queryEntities( + table: string, + options: Models.TableQueryEntitiesOptionalParams, + context: Context + ): Promise; + queryEntitiesWithPartitionAndRowKey( + table: string, + partitionKey: string, + rowKey: string, + options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, + context: Context + ): Promise; + updateEntity( + table: string, + partitionKey: string, + rowKey: string, + options: Models.TableUpdateEntityOptionalParams, + context: Context + ): Promise; + mergeEntity( + table: string, + partitionKey: string, + rowKey: string, + options: Models.TableMergeEntityOptionalParams, + context: Context + ): Promise; + deleteEntity( + table: string, + partitionKey: string, + rowKey: string, + ifMatch: string, + options: Models.TableDeleteEntityOptionalParams, + context: Context + ): Promise; + insertEntity( + table: string, + options: Models.TableInsertEntityOptionalParams, + context: Context + ): Promise; + getAccessPolicy( + table: string, + options: Models.TableGetAccessPolicyOptionalParams, + context: Context + ): Promise; + setAccessPolicy( + table: string, + options: Models.TableSetAccessPolicyOptionalParams, + context: Context + ): Promise; } diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index e34972bdb..ca9f59c17 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -238,22 +238,54 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableUpdateEntityOptionalParams, context: Context ): Promise { - // e.g - // const tableCtx = new TableStorageContext(context); - // const accountName = tableCtx.account; - // const tableName = tableCtx.tableName; // Get tableName from context - // const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context - // const rowKey = tableCtx.rowKey!; // Get rowKey from context - // const entity = options.tableEntityProperties!; - // return { - // statusCode: 204, - // date: tableCtx.startTime, - // clientRequestId: "clientRequestId", - // requestId: "requestId", - // version: "version" - // }; - // TODO - throw new NotImplementedError(); + const tableCtx = new TableStorageContext(context); + const accountName = tableCtx.account; + const tableName = tableCtx.tableName!; // Get tableName from context + const ifMatch = options.ifMatch; + + // Test if all required parameter exist + if ( + !options.tableEntityProperties || + !options.tableEntityProperties.PartitionKey || + !options.tableEntityProperties.RowKey + ) { + throw StorageErrorFactory.getPropertiesNeedValue(context); + } + + // Test if etag is available + if (ifMatch === "" || ifMatch === undefined) { + throw StorageErrorFactory.getPreconditionFailed(context); + } + + // Entity, which is used to update an existing entity + const entity: IEntity = { + PartitionKey: options.tableEntityProperties.PartitionKey, + RowKey: options.tableEntityProperties.RowKey, + properties: options.tableEntityProperties, + lastModifiedTime: context.startTime!, + eTag: newEtag() + }; + + // Update entity + await this.metadataStore.updateTableEntity( + context, + tableName, + accountName!, + entity, + ifMatch + ); + + // Response definition + const response: Models.TableUpdateEntityResponse = { + clientRequestId: options.requestId, + requestId: tableCtx.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + eTag: newEtag(), + statusCode: 204 + }; + + return response; } public async mergeEntity( diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index 656c381d0..28b848ed5 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -45,9 +45,10 @@ export default interface ITableMetadataStore { ): Promise<{ [propertyName: string]: any }[]>; updateTableEntity( context: Context, - table: string, - partitionKey: string, - rowKey: string + tableName: string, + account: string, + entity: IEntity, + eatg: string ): Promise; mergeTableEntity( context: Context, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index 549fc49e0..9602350a9 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -56,7 +56,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { this.db.addCollection(uniqueTableName, { // Optimization for indexing and searching // https://rawgit.com/techfort/LokiJS/master/jsdoc/tutorial-Indexing%20and%20Query%20performance.html - indices: ["ParititionKey", "RowKey"] + indices: ["PartitionKey", "RowKey"] }); // Optimize for find operation } @@ -143,12 +143,38 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async updateTableEntity( context: Context, - table: string, - partitionKey: string, - rowKey: string + tableName: string, + account: string, + entity: IEntity, + etag: string ): Promise { - // TODO - throw new NotImplementedError(); + const tableColl = this.db.getCollection( + this.getUniqueTableCollectionName(account, tableName) + ); + + // Throw error, if table not exists + if (!tableColl) { + throw StorageErrorFactory.getTableNotExist(context); + } + + // Get Current Doc + const currentDoc = tableColl.findOne({ + PartitionKey: entity.PartitionKey, + RowKey: entity.RowKey + }) as IEntity; + + // Throw error, if doc does not exist + if (!currentDoc) { + throw StorageErrorFactory.getEntityNotExist(context); + } else { + // Test if etag value is valid + if (etag !== "*" && currentDoc.eTag !== etag) { + throw StorageErrorFactory.getPreconditionFailed(context); + } + } + + tableColl.remove(currentDoc); + tableColl.insert(entity); } public async mergeTableEntity( diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 1c83cf9a9..ec1750067 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -10,6 +10,7 @@ import { getUniqueName, overrideRequest } from "../../testutils"; +import StorageError from "../../../src/blob/errors/StorageError"; // Set true to enable debug log configLogger(false); @@ -178,4 +179,141 @@ describe("table Entity APIs test", () => { } ); }); + + it("Update an Entity that exists, @loki", done => { + const entityInsert = { + PartitionKey: "part1", + RowKey: "row3", + myValue: "oldValue" + }; + tableService.insertEntity( + tableName, + entityInsert, + (error, result, insertresponse) => { + if (!error) { + requestOverride.headers = {}; + tableService.replaceEntity( + tableName, + { PartitionKey: "part1", RowKey: "row3", myValue: "newValue" }, + (updateError, updateResult, updateResponse) => { + if (!updateError) { + assert.equal(updateResponse.statusCode, 204); // Precondition succeeded + done(); + } else { + assert.ifError(updateError); + done(); + } + } + ); + } else { + assert.ifError(error); + done(); + } + } + ); + }); + + it("Update an Entity that does not exist, @loki", done => { + tableService.replaceEntity( + tableName, + { PartitionKey: "part1", RowKey: "row4", myValue: "newValue" }, + (updateError, updateResult, updateResponse) => { + const castUpdateStatusCode = (updateError as StorageError).statusCode; + if (updateError) { + assert.equal(castUpdateStatusCode, 409); + done(); + } else { + assert.fail("Test failed to throw the right Error" + updateError); + } + } + ); + }); + + it("Should not update an Entity not matching Etag, @loki", done => { + const entityInsert = { + PartitionKey: "part1", + RowKey: "row4", + myValue: "oldValue" + }; + const entityUpdate = { + PartitionKey: "part1", + RowKey: "row4", + myValue: "oldValueUpdate", + ".metadata": { + etag: "0x2252C97588D4000" + } + }; + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + tableService.insertEntity( + tableName, + entityInsert, + (insertError, insertResult, insertResponse) => { + if (!insertError) { + requestOverride.headers = {}; + tableService.replaceEntity( + tableName, + entityUpdate, + (updateError, updateResponse) => { + const castUpdateStatusCode = (updateError as StorageError) + .statusCode; + assert.equal(castUpdateStatusCode, 412); // Precondition failed + done(); + } + ); + } else { + assert.ifError(insertError); + done(); + } + } + ); + }); + + it("Should update, if Etag matches, @loki", done => { + const entityInsert = { + PartitionKey: "part1", + RowKey: "row5", + myValue: "oldValue" + }; + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + tableService.insertEntity( + tableName, + entityInsert, + (error, result, insertresponse) => { + const etagOld = result[".metadata"].etag; + const entityUpdate = { + PartitionKey: "part1", + RowKey: "row5", + myValue: "oldValueUpdate", + ".metadata": { + etag: etagOld + } + }; + if (!error) { + requestOverride.headers = {}; + tableService.replaceEntity( + tableName, + entityUpdate, + (updateError, updateResult, updateResponse) => { + if (!updateError) { + assert.equal(updateResponse.statusCode, 204); // Precondition succeeded + done(); + } else { + assert.ifError(updateError); + done(); + } + } + ); + } else { + assert.ifError(error); + done(); + } + } + ); + }); }); From b2c1af6d7f1ae5425e1d74ec45c15f9ac0f5bfac Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Wed, 2 Sep 2020 15:49:10 +0800 Subject: [PATCH 10/57] Workaround to support HTTP Merge for Merge Entity (#544) --- src/table/generated/artifacts/mappers.ts | 46 +++++++++ src/table/generated/artifacts/models.ts | 98 ++++++++++++++++++- src/table/generated/artifacts/operation.ts | 1 + .../generated/artifacts/specifications.ts | 52 +++++++++- src/table/generated/handlers/ITableHandler.ts | 75 +++----------- .../generated/handlers/handlerMappers.ts | 10 ++ src/table/handlers/TableHandler.ts | 18 +++- swagger/table.md | 11 +++ 8 files changed, 244 insertions(+), 67 deletions(-) diff --git a/src/table/generated/artifacts/mappers.ts b/src/table/generated/artifacts/mappers.ts index 40f3992c6..099354f1e 100644 --- a/src/table/generated/artifacts/mappers.ts +++ b/src/table/generated/artifacts/mappers.ts @@ -921,6 +921,52 @@ export const TableDeleteEntityHeaders: msRest.CompositeMapper = { } }; +export const TableMergeEntityWithMergeHeaders: msRest.CompositeMapper = { + serializedName: "table-mergeentitywithmerge-headers", + type: { + name: "Composite", + className: "TableMergeEntityWithMergeHeaders", + modelProperties: { + clientRequestId: { + serializedName: "x-ms-client-request-id", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + eTag: { + serializedName: "etag", + type: { + name: "String" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + export const TableInsertEntityHeaders: msRest.CompositeMapper = { serializedName: "table-insertentity-headers", type: { diff --git a/src/table/generated/artifacts/models.ts b/src/table/generated/artifacts/models.ts index 80fd9a447..3541c48b9 100644 --- a/src/table/generated/artifacts/models.ts +++ b/src/table/generated/artifacts/models.ts @@ -525,7 +525,7 @@ export interface TableDeleteEntityOptionalParams { /** * Optional Parameters. */ -export interface TableInsertEntityOptionalParams { +export interface TableMergeEntityWithMergeOptionalParams { /** * The timeout parameter is expressed in seconds. */ @@ -543,6 +543,40 @@ export interface TableInsertEntityOptionalParams { * The properties for the table entity. */ tableEntityProperties?: { [propertyName: string]: any }; + /** + * Match condition for an entity to be updated. If specified and a matching entity is not found, + * an error will be raised. To force an unconditional update, set to the wildcard character (*). + * If not specified, an insert will be performed when no existing entity is found to update and a + * merge will be performed if an existing entity is found. + */ + ifMatch?: string; + /** + * Additional parameters for the operation + */ + queryOptions?: QueryOptions; +} + +/** + * Optional Parameters. + */ +export interface TableInsertEntityOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion8; + /** + * The properties for the table entity. + */ + tableEntityProperties?: { [propertyName: string]: any }; /** * Specifies whether the response should include the inserted entity in the payload. Possible * values are return-no-content and return-content. Possible values include: 'return-no-content', @@ -890,6 +924,38 @@ export interface TableDeleteEntityHeaders { errorCode?: string; } +/** + * Defines headers for MergeEntityWithMerge operation. + */ +export interface TableMergeEntityWithMergeHeaders { + /** + * If a client request id header is sent in the request, this header will be present in the + * response with the same value. + */ + clientRequestId?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Table service used to execute the request. This header is + * returned for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + /** + * UTC date/time value generated by the service that indicates the time at which the entity was + * last updated. + */ + eTag?: string; + errorCode?: string; +} + /** * Defines headers for InsertEntity operation. */ @@ -1184,6 +1250,16 @@ export enum DataServiceVersion7 { ThreeFullStopZero = '3.0', } +/** + * Defines values for DataServiceVersion8. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion8 { + ThreeFullStopZero = '3.0', +} + /** * Defines values for Version1. * Possible values include: '2019-02-02' @@ -1324,6 +1400,16 @@ export enum Version14 { TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', } +/** + * Defines values for Version15. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version15 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + /** * Contains response data for the query operation. */ @@ -1404,6 +1490,16 @@ export type TableDeleteEntityResponse = TableDeleteEntityHeaders & { statusCode: 204; }; +/** + * Contains response data for the mergeEntityWithMerge operation. + */ +export type TableMergeEntityWithMergeResponse = TableMergeEntityWithMergeHeaders & { + /** + * The response status code. + */ + statusCode: 204; +}; + /** * Contains response data for the insertEntity operation. */ diff --git a/src/table/generated/artifacts/operation.ts b/src/table/generated/artifacts/operation.ts index 7e8215020..17d30a576 100644 --- a/src/table/generated/artifacts/operation.ts +++ b/src/table/generated/artifacts/operation.ts @@ -15,6 +15,7 @@ export enum Operation { Table_UpdateEntity, Table_MergeEntity, Table_DeleteEntity, + Table_MergeEntityWithMerge, Table_InsertEntity, Table_GetAccessPolicy, Table_SetAccessPolicy, diff --git a/src/table/generated/artifacts/specifications.ts b/src/table/generated/artifacts/specifications.ts index dd98ebb2b..2d008897f 100644 --- a/src/table/generated/artifacts/specifications.ts +++ b/src/table/generated/artifacts/specifications.ts @@ -302,6 +302,54 @@ const tableDeleteEntityOperationSpec: msRest.OperationSpec = { serializer }; +const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { + httpMethod: "POST", + path: "{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')", + urlParameters: [ + Parameters.url, + Parameters.table, + Parameters.partitionKey, + Parameters.rowKey + ], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion, + Parameters.ifMatch0 + ], + requestBody: { + parameterPath: [ + "options", + "tableEntityProperties" + ], + mapper: { + serializedName: "tableEntityProperties", + type: { + name: "Dictionary", + value: { + type: { + name: "Object" + } + } + } + } + }, + responses: { + 204: { + headersMapper: Mappers.TableMergeEntityWithMergeHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + const tableInsertEntityOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "{table}", @@ -540,11 +588,11 @@ Specifications[Operation.Table_Query] = tableQueryOperationSpec; Specifications[Operation.Table_Create] = tableCreateOperationSpec; Specifications[Operation.Table_Delete] = tableDeleteOperationSpec; Specifications[Operation.Table_QueryEntities] = tableQueryEntitiesOperationSpec; -Specifications[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = -tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; +Specifications[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; Specifications[Operation.Table_UpdateEntity] = tableUpdateEntityOperationSpec; Specifications[Operation.Table_MergeEntity] = tableMergeEntityOperationSpec; Specifications[Operation.Table_DeleteEntity] = tableDeleteEntityOperationSpec; +Specifications[Operation.Table_MergeEntityWithMerge] = tableMergeEntityWithMergeOperationSpec; Specifications[Operation.Table_InsertEntity] = tableInsertEntityOperationSpec; Specifications[Operation.Table_GetAccessPolicy] = tableGetAccessPolicyOperationSpec; Specifications[Operation.Table_SetAccessPolicy] = tableSetAccessPolicyOperationSpec; diff --git a/src/table/generated/handlers/ITableHandler.ts b/src/table/generated/handlers/ITableHandler.ts index 9237f6d5c..9c5f2769e 100644 --- a/src/table/generated/handlers/ITableHandler.ts +++ b/src/table/generated/handlers/ITableHandler.ts @@ -13,67 +13,16 @@ import * as Models from "../artifacts/models"; import Context from "../Context"; export default interface ITableHandler { - query( - options: Models.TableQueryOptionalParams, - context: Context - ): Promise; - create( - tableProperties: Models.TableProperties, - options: Models.TableCreateOptionalParams, - context: Context - ): Promise; - delete( - table: string, - options: Models.TableDeleteMethodOptionalParams, - context: Context - ): Promise; - queryEntities( - table: string, - options: Models.TableQueryEntitiesOptionalParams, - context: Context - ): Promise; - queryEntitiesWithPartitionAndRowKey( - table: string, - partitionKey: string, - rowKey: string, - options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, - context: Context - ): Promise; - updateEntity( - table: string, - partitionKey: string, - rowKey: string, - options: Models.TableUpdateEntityOptionalParams, - context: Context - ): Promise; - mergeEntity( - table: string, - partitionKey: string, - rowKey: string, - options: Models.TableMergeEntityOptionalParams, - context: Context - ): Promise; - deleteEntity( - table: string, - partitionKey: string, - rowKey: string, - ifMatch: string, - options: Models.TableDeleteEntityOptionalParams, - context: Context - ): Promise; - insertEntity( - table: string, - options: Models.TableInsertEntityOptionalParams, - context: Context - ): Promise; - getAccessPolicy( - table: string, - options: Models.TableGetAccessPolicyOptionalParams, - context: Context - ): Promise; - setAccessPolicy( - table: string, - options: Models.TableSetAccessPolicyOptionalParams, - context: Context - ): Promise; + query(options: Models.TableQueryOptionalParams, context: Context): Promise; + create(tableProperties: Models.TableProperties, options: Models.TableCreateOptionalParams, context: Context): Promise; + delete(table: string, options: Models.TableDeleteMethodOptionalParams, context: Context): Promise; + queryEntities(table: string, options: Models.TableQueryEntitiesOptionalParams, context: Context): Promise; + queryEntitiesWithPartitionAndRowKey(table: string, partitionKey: string, rowKey: string, options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, context: Context): Promise; + updateEntity(table: string, partitionKey: string, rowKey: string, options: Models.TableUpdateEntityOptionalParams, context: Context): Promise; + mergeEntity(table: string, partitionKey: string, rowKey: string, options: Models.TableMergeEntityOptionalParams, context: Context): Promise; + deleteEntity(table: string, partitionKey: string, rowKey: string, ifMatch: string, options: Models.TableDeleteEntityOptionalParams, context: Context): Promise; + mergeEntityWithMerge(table: string, partitionKey: string, rowKey: string, options: Models.TableMergeEntityWithMergeOptionalParams, context: Context): Promise; + insertEntity(table: string, options: Models.TableInsertEntityOptionalParams, context: Context): Promise; + getAccessPolicy(table: string, options: Models.TableGetAccessPolicyOptionalParams, context: Context): Promise; + setAccessPolicy(table: string, options: Models.TableSetAccessPolicyOptionalParams, context: Context): Promise; } diff --git a/src/table/generated/handlers/handlerMappers.ts b/src/table/generated/handlers/handlerMappers.ts index f1545df96..f120788d5 100644 --- a/src/table/generated/handlers/handlerMappers.ts +++ b/src/table/generated/handlers/handlerMappers.ts @@ -82,6 +82,16 @@ operationHandlerMapping[Operation.Table_DeleteEntity] = { handler: "tableHandler", method: "deleteEntity" }; +operationHandlerMapping[Operation.Table_MergeEntityWithMerge] = { + arguments: [ + "table", + "partitionKey", + "rowKey", + "options" + ], + handler: "tableHandler", + method: "mergeEntityWithMerge" +}; operationHandlerMapping[Operation.Table_InsertEntity] = { arguments: [ "table", diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index ca9f59c17..2b32271c1 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -14,7 +14,7 @@ import { NO_METADATA_ACCEPT, RETURN_CONTENT, RETURN_NO_CONTENT, - TABLE_API_VERSION + TABLE_API_VERSION, } from "../utils/constants"; import { newEtag } from "../utils/utils"; import BaseHandler from "./BaseHandler"; @@ -313,6 +313,22 @@ export default class TableHandler extends BaseHandler implements ITableHandler { throw new NotImplementedError(); } + public async mergeEntityWithMerge( + table: string, + partitionKey: string, + rowKey: string, + options: Models.TableMergeEntityWithMergeOptionalParams, + context: Context + ): Promise { + return this.mergeEntity( + table, + partitionKey, + rowKey, + options as any, + context + ); + } + public async deleteEntity( _table: string, _partitionKey: string, diff --git a/swagger/table.md b/swagger/table.md index 8463bd77d..0eb1f1724 100644 --- a/swagger/table.md +++ b/swagger/table.md @@ -79,4 +79,15 @@ directive: "type": "object", "format": "file" }; +``` + +### Add Post Method for Table_MergeEntity + +```yaml +directive: + - from: swagger-document + where: $["paths"]["/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')"] + transform: > + $.post = {...$.patch}; + $.post.operationId = "Table_MergeEntityWithMerge" ``` \ No newline at end of file From a6f484d873ac9e99ebbd08ac9766ecec88dd6787 Mon Sep 17 00:00:00 2001 From: Yi Lyu <41231856+isabella0428@users.noreply.github.com> Date: Wed, 2 Sep 2020 17:33:45 +0800 Subject: [PATCH 11/57] modify post verb to merge (#545) * modify post verb to merge * Fix CI --- src/table/TableRequestListenerFactory.ts | 17 +- .../generated/artifacts/specifications.ts | 185 +++++------------- 2 files changed, 69 insertions(+), 133 deletions(-) diff --git a/src/table/TableRequestListenerFactory.ts b/src/table/TableRequestListenerFactory.ts index ed409151f..9104bf18a 100644 --- a/src/table/TableRequestListenerFactory.ts +++ b/src/table/TableRequestListenerFactory.ts @@ -54,6 +54,17 @@ export default class TableRequestListenerFactory (Specifications[operation] as MutableSpecification).isXML = false; }); + // TODO: MERGE verbs is not supported by auto generator yet, + // So there we generate a post method and change the verb for MERGE here + Object.defineProperty( + Specifications[Operation.Table_MergeEntityWithMerge], + "httpMethod", + { + value: "MERGE", + writable: false + } + ); + const app = express().disable("x-powered-by"); // MiddlewareFactory is a factory to create auto-generated middleware @@ -75,7 +86,11 @@ export default class TableRequestListenerFactory // Access log per request if (this.enableAccessLog) { - app.use(morgan("common", { stream: this.accessLogWriteStream })); + app.use( + morgan("common", { + stream: this.accessLogWriteStream + }) + ); } // Manually created middleware to deserialize feature related context which swagger doesn't know diff --git a/src/table/generated/artifacts/specifications.ts b/src/table/generated/artifacts/specifications.ts index 2d008897f..278ba7e56 100644 --- a/src/table/generated/artifacts/specifications.ts +++ b/src/table/generated/artifacts/specifications.ts @@ -20,9 +20,7 @@ const serializer = new msRest.Serializer(Mappers, true); const tableQueryOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "Tables", - urlParameters: [ - Parameters.url - ], + urlParameters: [Parameters.url], queryParameters: [ Parameters.nextTableName, Parameters.format, @@ -49,12 +47,8 @@ const tableQueryOperationSpec: msRest.OperationSpec = { const tableCreateOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "Tables", - urlParameters: [ - Parameters.url - ], - queryParameters: [ - Parameters.format - ], + urlParameters: [Parameters.url], + queryParameters: [Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -88,14 +82,8 @@ const tableCreateOperationSpec: msRest.OperationSpec = { const tableDeleteOperationSpec: msRest.OperationSpec = { httpMethod: "DELETE", path: "Tables('{table}')", - urlParameters: [ - Parameters.url, - Parameters.table - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url, Parameters.table], + headerParameters: [Parameters.version, Parameters.requestId], responses: { 204: { headersMapper: Mappers.TableDeleteHeaders @@ -111,10 +99,7 @@ const tableDeleteOperationSpec: msRest.OperationSpec = { const tableQueryEntitiesOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "{table}()", - urlParameters: [ - Parameters.url, - Parameters.table - ], + urlParameters: [Parameters.url, Parameters.table], queryParameters: [ Parameters.timeout, Parameters.nextPartitionKey, @@ -184,10 +169,7 @@ const tableUpdateEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -195,10 +177,7 @@ const tableUpdateEntityOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: [ - "options", - "tableEntityProperties" - ], + parameterPath: ["options", "tableEntityProperties"], mapper: { serializedName: "tableEntityProperties", type: { @@ -232,10 +211,7 @@ const tableMergeEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -243,10 +219,7 @@ const tableMergeEntityOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: [ - "options", - "tableEntityProperties" - ], + parameterPath: ["options", "tableEntityProperties"], mapper: { serializedName: "tableEntityProperties", type: { @@ -280,10 +253,7 @@ const tableDeleteEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -311,10 +281,7 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -322,10 +289,7 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: [ - "options", - "tableEntityProperties" - ], + parameterPath: ["options", "tableEntityProperties"], mapper: { serializedName: "tableEntityProperties", type: { @@ -353,14 +317,8 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { const tableInsertEntityOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "{table}", - urlParameters: [ - Parameters.url, - Parameters.table - ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + urlParameters: [Parameters.url, Parameters.table], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -368,10 +326,7 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { Parameters.responsePreference ], requestBody: { - parameterPath: [ - "options", - "tableEntityProperties" - ], + parameterPath: ["options", "tableEntityProperties"], mapper: { serializedName: "tableEntityProperties", type: { @@ -409,18 +364,9 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "{table}", - urlParameters: [ - Parameters.url, - Parameters.table - ], - queryParameters: [ - Parameters.timeout, - Parameters.comp0 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url, Parameters.table], + queryParameters: [Parameters.timeout, Parameters.comp0], + headerParameters: [Parameters.version, Parameters.requestId], responses: { 200: { bodyMapper: { @@ -449,23 +395,11 @@ const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { httpMethod: "PUT", path: "{table}", - urlParameters: [ - Parameters.url, - Parameters.table - ], - queryParameters: [ - Parameters.timeout, - Parameters.comp0 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url, Parameters.table], + queryParameters: [Parameters.timeout, Parameters.comp0], + headerParameters: [Parameters.version, Parameters.requestId], requestBody: { - parameterPath: [ - "options", - "tableAcl" - ], + parameterPath: ["options", "tableAcl"], mapper: { xmlName: "SignedIdentifiers", xmlElementName: "SignedIdentifier", @@ -497,18 +431,9 @@ const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { // specifications for new method group start const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { httpMethod: "PUT", - urlParameters: [ - Parameters.url - ], - queryParameters: [ - Parameters.timeout, - Parameters.restype, - Parameters.comp1 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url], + queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp1], + headerParameters: [Parameters.version, Parameters.requestId], requestBody: { parameterPath: "tableServiceProperties", mapper: { @@ -531,18 +456,9 @@ const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { httpMethod: "GET", - urlParameters: [ - Parameters.url - ], - queryParameters: [ - Parameters.timeout, - Parameters.restype, - Parameters.comp1 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url], + queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp1], + headerParameters: [Parameters.version, Parameters.requestId], responses: { 200: { bodyMapper: Mappers.TableServiceProperties, @@ -558,18 +474,9 @@ const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { const serviceGetStatisticsOperationSpec: msRest.OperationSpec = { httpMethod: "GET", - urlParameters: [ - Parameters.url - ], - queryParameters: [ - Parameters.timeout, - Parameters.restype, - Parameters.comp2 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url], + queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp2], + headerParameters: [Parameters.version, Parameters.requestId], responses: { 200: { bodyMapper: Mappers.TableServiceStats, @@ -588,15 +495,29 @@ Specifications[Operation.Table_Query] = tableQueryOperationSpec; Specifications[Operation.Table_Create] = tableCreateOperationSpec; Specifications[Operation.Table_Delete] = tableDeleteOperationSpec; Specifications[Operation.Table_QueryEntities] = tableQueryEntitiesOperationSpec; -Specifications[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; +Specifications[ + Operation.Table_QueryEntitiesWithPartitionAndRowKey +] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; Specifications[Operation.Table_UpdateEntity] = tableUpdateEntityOperationSpec; Specifications[Operation.Table_MergeEntity] = tableMergeEntityOperationSpec; Specifications[Operation.Table_DeleteEntity] = tableDeleteEntityOperationSpec; -Specifications[Operation.Table_MergeEntityWithMerge] = tableMergeEntityWithMergeOperationSpec; +Specifications[ + Operation.Table_MergeEntityWithMerge +] = tableMergeEntityWithMergeOperationSpec; Specifications[Operation.Table_InsertEntity] = tableInsertEntityOperationSpec; -Specifications[Operation.Table_GetAccessPolicy] = tableGetAccessPolicyOperationSpec; -Specifications[Operation.Table_SetAccessPolicy] = tableSetAccessPolicyOperationSpec; -Specifications[Operation.Service_SetProperties] = serviceSetPropertiesOperationSpec; -Specifications[Operation.Service_GetProperties] = serviceGetPropertiesOperationSpec; -Specifications[Operation.Service_GetStatistics] = serviceGetStatisticsOperationSpec; +Specifications[ + Operation.Table_GetAccessPolicy +] = tableGetAccessPolicyOperationSpec; +Specifications[ + Operation.Table_SetAccessPolicy +] = tableSetAccessPolicyOperationSpec; +Specifications[ + Operation.Service_SetProperties +] = serviceSetPropertiesOperationSpec; +Specifications[ + Operation.Service_GetProperties +] = serviceGetPropertiesOperationSpec; +Specifications[ + Operation.Service_GetStatistics +] = serviceGetStatisticsOperationSpec; export default Specifications; From 90ac5f36248659085975a300fdfd68e986b24826 Mon Sep 17 00:00:00 2001 From: "Ziheng Zhou(MSFT)" Date: Fri, 4 Sep 2020 12:42:20 +0800 Subject: [PATCH 12/57] Add table query feature (#536) * Add table query entity feature * Add table query feature * Add query table feature * Add table query feature * Add table query feature * update for CI error * update for CI error * update table.test.ts * add parameter accountName to query method in metadata layer * update tablehandler.ts --- src/table/handlers/TableHandler.ts | 88 +++++++++++++++---- src/table/persistence/ITableMetadataStore.ts | 5 +- .../persistence/LokiTableMetadataStore.ts | 26 +++++- tests/table/apis/table.test.ts | 80 +++++++++++++++++ 4 files changed, 176 insertions(+), 23 deletions(-) diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 2b32271c1..6855ea2ab 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -116,25 +116,75 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableQueryOptionalParams, context: Context ): Promise { - // TODO - // e.g - // return { - // statusCode: 200, - // clientRequestId: "clientRequestId", - // requestId: "requestId", - // version: "version", - // xMsContinuationNextTableName: "xMsContinuationNextTableName", - // odatametadata: "odatametadata", - // value: [ - // { - // tableName: "tableName", - // odatatype: "odatatype", - // odataid: "odataid", - // odataeditLink: "odataeditLink" - // } - // ] - // }; - throw new NotImplementedError(); + const tableCtx = new TableStorageContext(context); + const accountName = tableCtx.account; + + const accept = context.request!.getHeader("accept"); + + if ( + accept !== NO_METADATA_ACCEPT && + accept !== MINIMAL_METADATA_ACCEPT && + accept !== FULL_METADATA_ACCEPT + ) { + throw StorageErrorFactory.getContentTypeNotSupported(context); + } + + if (accountName === undefined) { + throw StorageErrorFactory.getAccountNameEmpty(context); + } + + const metadata = `${accountName}/$metadata#Tables`; + const tableResult = await this.metadataStore.queryTable( + context, + accountName + ); + + const response: Models.TableQueryResponse2 = { + clientRequestId: options.requestId, + requestId: tableCtx.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode: 200, + xMsContinuationNextTableName: options.nextTableName, + value: [] + }; + + let protocol = "http"; + let host = + DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; + // TODO: Get host and port from Azurite Server instance + if (tableCtx.request !== undefined) { + host = tableCtx.request.getHeader("host") as string; + protocol = tableCtx.request.getProtocol() as string; + } + + if (tableCtx.accept === NO_METADATA_ACCEPT) { + response.value = tableResult.map(item => { + return { tableName: item.tableName }; + }); + } + + if (tableCtx.accept === MINIMAL_METADATA_ACCEPT) { + response.odatametadata = `${protocol}://${host}/${metadata}`; + response.value = tableResult.map(item => { + return { tableName: item.tableName }; + }); + } + + if (tableCtx.accept === FULL_METADATA_ACCEPT) { + response.odatametadata = `${protocol}://${host}/${metadata}`; + response.value = tableResult.map(item => { + return { + odatatype: item.odatatype, + odataid: `${protocol}://${host}/${item.odataid}`, + odataeditLink: item.odataeditLink, + tableName: item.tableName + }; + }); + } + + context.response!.setContentType(accept); + return response; } public async delete( diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index 28b848ed5..8051738ef 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -25,7 +25,10 @@ export interface IEntity { export type TableModel = ITtableAdditionalProperties; export default interface ITableMetadataStore { - queryTable(context: Context): Promise; + queryTable( + context: Context, + accountName: string + ): Promise; createTable(context: Context, table: TableModel): Promise; deleteTable( context: Context, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index 9602350a9..c0bcfffad 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -87,10 +87,30 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { } public async queryTable( - context: Context + context: Context, + accountName: string ): Promise { - // TODO - throw new NotImplementedError(); + const coll = this.db.getCollection(this.TABLE_COLLECTION); + const docList = coll.find({ account: accountName }); + + if (!docList) { + throw StorageErrorFactory.getEntityNotFound(context); + } + + let response: Models.TableResponseProperties[] = []; + + if (docList.length > 0) { + response = docList.map(item => { + return { + odatatype: item.odatatype, + odataid: item.odataid, + odataeditLink: item.odataeditLink, + tableName: item.tableName + }; + }); + } + + return response; } public async deleteTable( diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index 4f632177d..ab2584549 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -126,6 +126,86 @@ describe("table APIs test", () => { done(); }); + it("queryTable, accept=application/json;odata=fullmetadata @loki", done => { + /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, + thus we workaround this by override request headers to test following 3 OData levels responses. + - application/json;odata=nometadata + - application/json;odata=minimalmetadata + - application/json;odata=fullmetadata + */ + requestOverride.headers = { + accept: "application/json;odata=fullmetadata" + }; + + tableService.listTablesSegmented(null as any, (error, result, response) => { + if (!error) { + assert.equal(response.statusCode, 200); + const headers = response.headers!; + assert.equal(headers["x-ms-version"], TABLE_API_VERSION); + const bodies = response.body! as any; + assert.deepStrictEqual( + bodies["odata.metadata"], + `${protocol}://${host}:${port}/${accountName}/$metadata#Tables` + ); + assert.ok(bodies.TableResponseProperties[0]["TableName"]); + assert.ok(bodies.TableResponseProperties[0]["odata.type"]); + assert.ok(bodies.TableResponseProperties[0]["odata.id"]); + assert.ok(bodies.TableResponseProperties[0]["odata.editLink"]); + } + done(); + }); + }); + + it("queryTable, accept=application/json;odata=minimalmetadata @loki", done => { + /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, + thus we workaround this by override request headers to test following 3 OData levels responses. + - application/json;odata=nometadata + - application/json;odata=minimalmetadata + - application/json;odata=fullmetadata + */ + requestOverride.headers = { + accept: "application/json;odata=minimalmetadata" + }; + + tableService.listTablesSegmented(null as any, (error, result, response) => { + if (!error) { + assert.equal(response.statusCode, 200); + const headers = response.headers!; + assert.equal(headers["x-ms-version"], TABLE_API_VERSION); + const bodies = response.body! as any; + assert.deepStrictEqual( + bodies["odata.metadata"], + `${protocol}://${host}:${port}/${accountName}/$metadata#Tables` + ); + assert.ok(bodies.TableResponseProperties[0]["TableName"]); + } + done(); + }); + }); + + it("queryTable, accept=application/json;odata=nometadata @loki", done => { + /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, + thus we workaround this by override request headers to test following 3 OData levels responses. + - application/json;odata=nometadata + - application/json;odata=minimalmetadata + - application/json;odata=fullmetadata + */ + requestOverride.headers = { + accept: "application/json;odata=nometadata" + }; + + tableService.listTablesSegmented(null as any, (error, result, response) => { + if (!error) { + assert.equal(response.statusCode, 200); + const headers = response.headers!; + assert.equal(headers["x-ms-version"], TABLE_API_VERSION); + const bodies = response.body! as any; + assert.ok(bodies.TableResponseProperties[0]["TableName"]); + } + done(); + }); + }); + it("deleteTable that exists, @loki", done => { /* https://docs.microsoft.com/en-us/rest/api/storageservices/delete-table From 3fe607eb09320b81ebe02acae9b5b03571a38817 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Thu, 17 Sep 2020 11:11:52 +0200 Subject: [PATCH 13/57] [Table] Phase 1 Feature - Insert Or Replace Entity (#552) * Upsert added incl query table entities with partition key and row key in the loki data handler * corrected testing for insert or update, changed etag validation in LokiTableMetadataStore updatetableentity --- src/table/handlers/TableHandler.ts | 58 ++++++++++++++----- src/table/persistence/ITableMetadataStore.ts | 5 +- .../persistence/LokiTableMetadataStore.ts | 32 +++++++--- tests/table/apis/table.entity.test.ts | 50 +++++++++++++++- tests/table/apis/table.test.ts | 6 +- 5 files changed, 123 insertions(+), 28 deletions(-) diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 6855ea2ab..29afea339 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -14,7 +14,7 @@ import { NO_METADATA_ACCEPT, RETURN_CONTENT, RETURN_NO_CONTENT, - TABLE_API_VERSION, + TABLE_API_VERSION } from "../utils/constants"; import { newEtag } from "../utils/utils"; import BaseHandler from "./BaseHandler"; @@ -303,35 +303,65 @@ export default class TableHandler extends BaseHandler implements ITableHandler { } // Test if etag is available - if (ifMatch === "" || ifMatch === undefined) { + // this is considered an upsert if no etag header, an empty header is an error. + // https://docs.microsoft.com/en-us/rest/api/storageservices/insert-or-replace-entity + if (ifMatch === "") { throw StorageErrorFactory.getPreconditionFailed(context); } - + const updateEtag = newEtag(); // Entity, which is used to update an existing entity const entity: IEntity = { PartitionKey: options.tableEntityProperties.PartitionKey, RowKey: options.tableEntityProperties.RowKey, properties: options.tableEntityProperties, lastModifiedTime: context.startTime!, - eTag: newEtag() + eTag: updateEtag }; - // Update entity - await this.metadataStore.updateTableEntity( - context, - tableName, - accountName!, - entity, - ifMatch - ); - + if (ifMatch !== undefined) { + // Update entity + await this.metadataStore.updateTableEntity( + context, + tableName, + accountName!, + entity, + ifMatch! + ); + } else { + // Upsert the entity + const exists = await this.metadataStore.queryTableEntitiesWithPartitionAndRowKey( + context, + tableName, + accountName!, + options.tableEntityProperties.PartitionKey, + options.tableEntityProperties.RowKey + ); + + if (exists !== null) { + // entity exists so we update and force with "*" etag + await this.metadataStore.updateTableEntity( + context, + tableName, + accountName!, + entity, + "*" + ); + } else { + await this.metadataStore.insertTableEntity( + context, + tableName, + accountName!, + entity + ); + } + } // Response definition const response: Models.TableUpdateEntityResponse = { clientRequestId: options.requestId, requestId: tableCtx.contextID, version: TABLE_API_VERSION, date: context.startTime, - eTag: newEtag(), + eTag: updateEtag, statusCode: 204 }; diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index 8051738ef..d662467d5 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -43,9 +43,10 @@ export default interface ITableMetadataStore { queryTableEntitiesWithPartitionAndRowKey( context: Context, table: string, + accountName: string, partitionKey: string, rowKey: string - ): Promise<{ [propertyName: string]: any }[]>; + ): Promise; updateTableEntity( context: Context, tableName: string, @@ -65,7 +66,7 @@ export default interface ITableMetadataStore { accountName: string, partitionKey: string, rowKey: string, - eatg: string + etag: string ): Promise; insertTableEntity( context: Context, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index c0bcfffad..ea5069128 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -153,12 +153,27 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async queryTableEntitiesWithPartitionAndRowKey( context: Context, - table: string, + tableName: string, + accountName: string, partitionKey: string, rowKey: string - ): Promise<{ [propertyName: string]: any }[]> { - // TODO - throw new NotImplementedError(); + ): Promise { + const tableColl = this.db.getCollection( + this.getUniqueTableCollectionName(accountName, tableName) + ); + + // Throw error, if table not exists + if (!tableColl) { + throw StorageErrorFactory.getTableNotExist(context); + } + + // Get requested Doc + const requestedDoc = tableColl.findOne({ + PartitionKey: partitionKey, + RowKey: rowKey + }) as IEntity; + + return requestedDoc; } public async updateTableEntity( @@ -188,13 +203,14 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { throw StorageErrorFactory.getEntityNotExist(context); } else { // Test if etag value is valid - if (etag !== "*" && currentDoc.eTag !== etag) { - throw StorageErrorFactory.getPreconditionFailed(context); + if (etag === "*" || currentDoc.eTag === etag) { + tableColl.remove(currentDoc); + tableColl.insert(entity); + return; } } - tableColl.remove(currentDoc); - tableColl.insert(entity); + throw StorageErrorFactory.getPreconditionFailed(context); } public async mergeTableEntity( diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index ec1750067..60bf22783 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -1,6 +1,7 @@ import * as assert from "assert"; import * as Azure from "azure-storage"; +import StorageError from "../../../src/blob/errors/StorageError"; import { configLogger } from "../../../src/common/Logger"; import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; @@ -10,7 +11,6 @@ import { getUniqueName, overrideRequest } from "../../testutils"; -import StorageError from "../../../src/blob/errors/StorageError"; // Set true to enable debug log configLogger(false); @@ -316,4 +316,52 @@ describe("table Entity APIs test", () => { } ); }); + + it("Insert or Replace (upsert) on an Entity that does not exist, @loki", done => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + tableService.insertOrReplaceEntity( + tableName, + { + PartitionKey: "part1", + RowKey: "row6", + myValue: "firstValue" + }, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 204); // No content + done(); + } + } + ); + }); + + it("Insert or Replace (upsert) on an Entity that exists, @loki", done => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + tableService.insertOrReplaceEntity( + tableName, + { + PartitionKey: "part1", + RowKey: "row6", + myValue: "newValue" + }, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 204); // No content + done(); + } + } + ); + }); }); diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index ab2584549..5f9fecf7b 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -147,7 +147,7 @@ describe("table APIs test", () => { bodies["odata.metadata"], `${protocol}://${host}:${port}/${accountName}/$metadata#Tables` ); - assert.ok(bodies.TableResponseProperties[0]["TableName"]); + assert.ok(bodies.TableResponseProperties[0].TableName); assert.ok(bodies.TableResponseProperties[0]["odata.type"]); assert.ok(bodies.TableResponseProperties[0]["odata.id"]); assert.ok(bodies.TableResponseProperties[0]["odata.editLink"]); @@ -177,7 +177,7 @@ describe("table APIs test", () => { bodies["odata.metadata"], `${protocol}://${host}:${port}/${accountName}/$metadata#Tables` ); - assert.ok(bodies.TableResponseProperties[0]["TableName"]); + assert.ok(bodies.TableResponseProperties[0].TableName); } done(); }); @@ -200,7 +200,7 @@ describe("table APIs test", () => { const headers = response.headers!; assert.equal(headers["x-ms-version"], TABLE_API_VERSION); const bodies = response.body! as any; - assert.ok(bodies.TableResponseProperties[0]["TableName"]); + assert.ok(bodies.TableResponseProperties[0].TableName); } done(); }); From b76c402c9f24b2a7feec930c1767d95937af10a6 Mon Sep 17 00:00:00 2001 From: Martha Splitthoff <31500919+CodeUnicornMartha@users.noreply.github.com> Date: Thu, 24 Sep 2020 11:33:38 +0200 Subject: [PATCH 14/57] Insert or merge entity#491 (#576) * changed TableHandler.ts for InsertorMerge and changed table.entity.test.ts * change TableHandler.ts in the mergeEntity section * changed tablehandler.ts, updated MergeEntity handler function, updated LokiTableMetdataStore.ts and ITableMetdataStore.ts * updated Merge and ItableMetdataStore and LokiTableMetdatastore * updated Merge and Insert Entity * updated Merge and Insert Entity --- package-lock.json | 5 ++ package.json | 1 + src/table/handlers/TableHandler.ts | 84 +++++++++++++++---- src/table/persistence/ITableMetadataStore.ts | 7 +- .../persistence/LokiTableMetadataStore.ts | 44 ++++++++-- tests/table/apis/table.entity.test.ts | 70 ++++++++++++++++ 6 files changed, 186 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6e1b5d174..0574691a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6212,6 +6212,11 @@ } } }, + "tsc": { + "version": "1.20150623.0", + "resolved": "https://registry.npmjs.org/tsc/-/tsc-1.20150623.0.tgz", + "integrity": "sha1-Trw8d04WkUjLx2inNCUz8ILHpuU=" + }, "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", diff --git a/package.json b/package.json index a87eafff7..febb47862 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "rimraf": "^2.6.3", "sequelize": "^5.18.4", "tedious": "^6.6.5", + "tsc": "^1.20150623.0", "tslib": "^1.9.3", "uri-templates": "^0.2.0", "uuid": "^3.3.2", diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 29afea339..b29cc6018 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -375,22 +375,74 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableMergeEntityOptionalParams, context: Context ): Promise { - // e.g - // const tableCtx = new TableStorageContext(context); - // const accountName = tableCtx.account; - // const tableName = tableCtx.tableName; // Get tableName from context - // const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context - // const rowKey = tableCtx.rowKey!; // Get rowKey from context - // const entity = options.tableEntityProperties!; - // return { - // statusCode: 204, - // date: tableCtx.startTime, - // clientRequestId: "clientRequestId", - // requestId: "requestId", - // version: "version" - // }; - // TODO - throw new NotImplementedError(); + const tableCtx = new TableStorageContext(context); + const accountName = tableCtx.account; + const tableName = tableCtx.tableName; + const partitionKey = tableCtx.partitionKey!; + const rowKey = tableCtx.rowKey!; + + if ( + !options.tableEntityProperties || + !options.tableEntityProperties.PartitionKey || + !options.tableEntityProperties.RowKey + ) { + throw StorageErrorFactory.getPropertiesNeedValue(context); + } + + const existingEntity = await this.metadataStore.queryTableEntitiesWithPartitionAndRowKey( + context, + tableName!, + accountName!, + partitionKey, + rowKey + ); + let etagValue = "*"; + + if (existingEntity !== null) { + const mergeEntity: IEntity = { + PartitionKey: options.tableEntityProperties.PartitionKey, + RowKey: options.tableEntityProperties.RowKey, + properties: options.tableEntityProperties, + lastModifiedTime: context.startTime!, + eTag: etagValue + }; + + etagValue = await this.metadataStore.mergeTableEntity( + context, + tableName!, + accountName!, + mergeEntity, + etagValue, + partitionKey, + rowKey + ); + } else { + const entity: IEntity = { + PartitionKey: options.tableEntityProperties.PartitionKey, + RowKey: options.tableEntityProperties.RowKey, + properties: options.tableEntityProperties, + lastModifiedTime: context.startTime!, + eTag: etagValue + }; + + await this.metadataStore.insertTableEntity( + context, + tableName!, + accountName!, + entity + ); + } + + const response: Models.TableMergeEntityResponse = { + clientRequestId: options.requestId, + requestId: tableCtx.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode: 204, + eTag: etagValue + }; + + return response; } public async mergeEntityWithMerge( diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index d662467d5..3a5cd3b12 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -56,10 +56,13 @@ export default interface ITableMetadataStore { ): Promise; mergeTableEntity( context: Context, - table: string, + tableName: string, + account: string, + entity: IEntity, + etag: string, partitionKey: string, rowKey: string - ): Promise; + ): Promise; deleteTableEntity( context: Context, tableName: string, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index ea5069128..a837c6be2 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -1,6 +1,6 @@ import { stat } from "fs"; import Loki from "lokijs"; - +import { newEtag } from "../../blob/utils/utils"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; import * as Models from "../generated/artifacts/models"; @@ -215,12 +215,42 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async mergeTableEntity( context: Context, - table: string, - partitionKey: string, - rowKey: string - ): Promise { - // TODO - throw new NotImplementedError(); + tableName: string, + account: string, + entity: IEntity, + etag: string + ): Promise { + const tableColl = this.db.getCollection( + this.getUniqueTableCollectionName(account, tableName) + ); + + // Throw error, if table not exists + if (!tableColl) { + throw StorageErrorFactory.getTableNotExist(context); + } + + // Get Current Doc + const currentDoc = tableColl.findOne({ + PartitionKey: entity.PartitionKey, + RowKey: entity.RowKey + }) as IEntity; + + // Throw error, if doc does not exist + if (!currentDoc) { + throw StorageErrorFactory.getEntityNotExist(context); + } else { + // Test if etag value is valid + if (etag === "*" || currentDoc.eTag === etag) { + const mergedDoc = { + ...currentDoc, + ...entity + }; + mergedDoc.eTag = newEtag(); + tableColl.update(mergedDoc); + return mergedDoc.eTag; + } + } + throw StorageErrorFactory.getPreconditionFailed(context); } public async deleteTableEntity( diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 60bf22783..17cd735a6 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -335,6 +335,7 @@ describe("table Entity APIs test", () => { done(); } else { assert.equal(updateResponse.statusCode, 204); // No content + // TODO When QueryEntity is done - validate Entity Properties done(); } } @@ -359,6 +360,75 @@ describe("table Entity APIs test", () => { done(); } else { assert.equal(updateResponse.statusCode, 204); // No content + // TODO When QueryEntity is done - validate Entity Properties + done(); + } + } + ); + }); + + it("Insert or Merge on an Entity that exists, @loki", done => { + const entityInsert = { + PartitionKey: "part1", + RowKey: "merge1", + myValue: "oldValue" + }; + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + tableService.insertEntity( + tableName, + entityInsert, + (error, result, insertresponse) => { + const entityUpdate = { + PartitionKey: "part1", + RowKey: "merge1", + mergeValue: "newValue" + }; + if (!error) { + requestOverride.headers = {}; + tableService.insertOrMergeEntity( + tableName, + entityUpdate, + (updateError, updateResult, updateResponse) => { + if (!updateError) { + assert.equal(updateResponse.statusCode, 204); // Precondition succeeded + // TODO When QueryEntity is done - validate Entity Properties + done(); + } else { + assert.ifError(updateError); + done(); + } + } + ); + } else { + assert.ifError(error); + done(); + } + } + ); + }); + + it("Insert or Merge on an Entity that does not exist, @loki", done => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + tableService.insertOrMergeEntity( + tableName, + { + PartitionKey: "part1", + RowKey: "row8", + myValue: "firstValue" + }, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 204); // No content + // TODO When QueryEntity is done - validate Entity Properties done(); } } From 2bc954c70ef087233884d6a0dde263e95948a046 Mon Sep 17 00:00:00 2001 From: Trevor Nichols Date: Thu, 24 Sep 2020 19:42:38 +1000 Subject: [PATCH 15/57] Add API Version check for table storage middleware (#555) --- src/table/TableRequestListenerFactory.ts | 5 ++-- src/table/TableServer.ts | 3 ++- src/table/errors/StorageErrorFactory.ts | 16 +++++++++++++ .../tableStorageContext.middleware.ts | 20 ++++++++++++---- src/table/utils/constants.ts | 24 +++++++++++++++++++ src/table/utils/utils.ts | 15 ++++++++++++ tests/table/apis/table.test.ts | 14 ++++++++++- 7 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/table/TableRequestListenerFactory.ts b/src/table/TableRequestListenerFactory.ts index 9104bf18a..0dc4f4628 100644 --- a/src/table/TableRequestListenerFactory.ts +++ b/src/table/TableRequestListenerFactory.ts @@ -32,7 +32,8 @@ export default class TableRequestListenerFactory public constructor( private readonly metadataStore: ITableMetadataStore, private readonly enableAccessLog: boolean, - private readonly accessLogWriteStream?: NodeJS.WritableStream // private readonly skipApiVersionCheck?: boolean, + private readonly accessLogWriteStream?: NodeJS.WritableStream, + private readonly skipApiVersionCheck?: boolean ) {} public createRequestListener(): RequestListener { @@ -94,7 +95,7 @@ export default class TableRequestListenerFactory } // Manually created middleware to deserialize feature related context which swagger doesn't know - app.use(createTableStorageContextMiddleware()); + app.use(createTableStorageContextMiddleware(this.skipApiVersionCheck)); // Dispatch incoming HTTP request to specific operation app.use(middlewareFactory.createDispatchMiddleware()); diff --git a/src/table/TableServer.ts b/src/table/TableServer.ts index dfedc78f6..b480e193a 100644 --- a/src/table/TableServer.ts +++ b/src/table/TableServer.ts @@ -58,7 +58,8 @@ export default class TableServer extends ServerBase { const requestListenerFactory: IRequestListenerFactory = new TableRequestListenerFactory( metadataStore, configuration.enableAccessLog, // Access log includes every handled HTTP request - configuration.accessLogWriteStream + configuration.accessLogWriteStream, + configuration.skipApiVersionCheck ); const host = configuration.host; diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 4e49b8432..ef2003956 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -10,6 +10,22 @@ import StorageError from "./StorageError"; const defaultID: string = "DefaultID"; export default class StorageErrorFactory { + public static getInvalidHeaderValue( + contextID: string = "", + additionalMessages?: { [key: string]: string } + ): StorageError { + if (additionalMessages === undefined) { + additionalMessages = {}; + } + return new StorageError( + 400, + "InvalidHeaderValue", + "The value for one of the HTTP headers is not in the correct format.", + contextID, + additionalMessages + ); + } + public static getTableAlreadyExists(context: Context): StorageError { return new StorageError( 409, diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index 025982d01..05fd403ef 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -6,12 +6,16 @@ import { PRODUCTION_STYLE_URL_HOSTNAME } from "../../common/utils/constants"; import TableStorageContext from "../context/TableStorageContext"; import { DEFAULT_TABLE_CONTEXT_PATH, - HeaderConstants + HeaderConstants, + ValidAPIVersions } from "../utils/constants"; +import { checkApiVersion } from "../utils/utils"; -export default function createTableStorageContextMiddleware(): RequestHandler { +export default function createTableStorageContextMiddleware( + skipApiVersionCheck?: boolean +): RequestHandler { return (req: Request, res: Response, next: NextFunction) => { - return tableStorageContextMiddleware(req, res, next); + return tableStorageContextMiddleware(req, res, next, skipApiVersionCheck); }; } @@ -26,7 +30,8 @@ export default function createTableStorageContextMiddleware(): RequestHandler { export function tableStorageContextMiddleware( req: Request, res: Response, - next: NextFunction + next: NextFunction, + skipApiVersionCheck?: boolean ): void { // Set server header in every Azurite response res.setHeader( @@ -36,6 +41,13 @@ export function tableStorageContextMiddleware( const requestID = uuid(); + if (!skipApiVersionCheck) { + const apiVersion = req.header(HeaderConstants.X_MS_VERSION); + if (apiVersion !== undefined) { + checkApiVersion(apiVersion, ValidAPIVersions, requestID); + } + } + const tableContext = new TableStorageContext( res.locals, DEFAULT_TABLE_CONTEXT_PATH diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index 948a4513a..df384855b 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -18,6 +18,7 @@ export const TABLE_API_VERSION = "2019-12-12"; export const HeaderConstants = { SERVER: "Server", VERSION: "3.8.0", + X_MS_VERSION: "x-ms-version", APPLICATION_JSON: "application/json" }; @@ -27,3 +28,26 @@ export const FULL_METADATA_ACCEPT = "application/json;odata=fullmetadata"; export const RETURN_NO_CONTENT = "return-no-content"; export const RETURN_CONTENT = "return-content"; + +export const ValidAPIVersions = [ + "2019-12-12", + "2019-07-07", + "2019-02-02", + "2018-11-09", + "2018-03-28", + "2017-11-09", + "2017-07-29", + "2017-04-17", + "2016-05-31", + "2015-12-11", + "2015-07-08", + "2015-04-05", + "2015-02-21", + "2014-02-14", + "2013-08-15", + "2012-02-12", + "2011-08-18", + "2009-09-19", + "2009-07-17", + "2009-04-14" +]; diff --git a/src/table/utils/utils.ts b/src/table/utils/utils.ts index 7bee02b19..6da84ffcf 100644 --- a/src/table/utils/utils.ts +++ b/src/table/utils/utils.ts @@ -1,3 +1,5 @@ +import StorageErrorFactory from "../errors/StorageErrorFactory"; + export function newEtag(): string { // Etag should match ^"0x[A-F0-9]{15,}"$ // Date().getTime().toString(16) only has 11 digital @@ -10,3 +12,16 @@ export function newEtag(): string { '"' ); } + +export function checkApiVersion( + inputApiVersion: string, + validApiVersions: Array, + requestId: string +): void { + if (!validApiVersions.includes(inputApiVersion)) { + throw StorageErrorFactory.getInvalidHeaderValue(requestId, { + HeaderName: "x-ms-version", + HeaderValue: inputApiVersion + }); + } +} diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index 5f9fecf7b..d6e4ab7ff 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -4,7 +4,10 @@ import * as Azure from "azure-storage"; import { configLogger } from "../../../src/common/Logger"; import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; -import { TABLE_API_VERSION } from "../../../src/table/utils/constants"; +import { + HeaderConstants, + TABLE_API_VERSION +} from "../../../src/table/utils/constants"; import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME, @@ -245,4 +248,13 @@ describe("table APIs test", () => { done(); }); }); + + it("createTable with invalid version, @loki", done => { + requestOverride.headers = { [HeaderConstants.X_MS_VERSION]: "invalid" }; + + tableService.createTable("test", (error, result) => { + assert.equal(result.statusCode, 400); + done(); + }); + }); }); From e2a8f4ec7b31efbfee52bf7e45d62164165660f6 Mon Sep 17 00:00:00 2001 From: Trevor Nichols Date: Fri, 25 Sep 2020 13:02:05 +1000 Subject: [PATCH 16/57] Update readme to include table changes (#574) * Add API Version check for table storage middleware * Update readme for table service --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.md b/README.md index 4130d2e6e..e88d2cf68 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,11 @@ Compared to V2, Azurite V3 implements a new architecture leveraging code generat - Preflight Request - Create/List/Delete Queues - Put/Get/Peek/Updata/Deleta/Clear Messages +- Table storage features align with Azure Storage API version 2019-12-12 (Refer to support matrix section below) + - SharedKey/Account SAS/Service SAS + - Get/Set Table Service Properties + - Create/List/Delete Tables + - Insert/Update/Query/Delete Table Entities - Features **NEW** on V3 - Built with TypeScript and ECMA native promise and async features - New architecture based on TypeScript server generator. Leverage auto generated protocol layer, models, serializer, deserializer and handler interfaces from REST API swagger @@ -97,6 +102,12 @@ Start queue service only: $ azurite-queue -l path/to/azurite/workspace ``` +Start table service only: + +```bash +$ azurite-table -l path/to/azurite/workspace +``` + ### Visual Studio Code Extension Azurite V3 can be installed from [Visual Studio Code extension market](https://marketplace.visualstudio.com/items?itemName=Azurite.azurite). @@ -121,6 +132,8 @@ Following extension configurations are supported: - `azurite.blobPort` Blob service listening port, by default 10000 - `azurite.queueHost` Queue service listening endpoint, by default 127.0.0.1 - `azurite.queuePort` Queue service listening port, by default 10001 +- `azurite.tableHost` Table service listening endpoint, by default 127.0.0.1 +- `azurite.tablePort` Table service listening port, by default 10002 - `azurite.location` Workspace location path, by default existing Visual Studio Code opened folder - `azurite.silent` Silent mode to disable access log in Visual Studio channel, by default false - `azurite.debug` Output debug log into Azurite channel, by default false @@ -211,6 +224,7 @@ You can customize the listening address per your requirements. ```cmd --blobHost 127.0.0.1 --queueHost 127.0.0.1 +--tableHost 127.0.0.1 ``` #### Allow Accepting Requests from Remote (potentially unsafe) @@ -218,6 +232,7 @@ You can customize the listening address per your requirements. ```cmd --blobHost 0.0.0.0 --queueHost 0.0.0.0 +--tableHost 0.0.0.0 ``` ### Listening Port Configuration @@ -232,6 +247,7 @@ You can customize the listening port per your requirements. ```cmd --blobPort 8888 --queuePort 9999 +--tablePort 11111 ``` #### Let System Auto Select an Available Port @@ -239,6 +255,7 @@ You can customize the listening port per your requirements. ```cmd --blobPort 0 --queuePort 0 +--tablePort 0 ``` > Note: The port in use is displayed on Azurite startup. @@ -849,6 +866,28 @@ Detailed support matrix: - Following features or REST APIs are NOT supported or limited supported in this release (will support more features per customers feedback in future releases) - SharedKey Lite +Latest version supports for **2019-12-12** API version **table** service. +Detailed support matrix: + +- Supported Vertical Features + - SharedKey Authentication + - Shared Access Signature Account Level + - Shared Access Signature Service Level +- Supported REST APIs + - List Tables + - Set Service Properties + - Get Service Properties + - Get Stats + - Create Table + - Get Table ACL + - Set Table ACL + - Delete Table + - Update Entity + - Query Entities + - Merge Entity + - Delete Entity + - Insert Entity + ## License This project is licensed under MIT. From e8a6e38967a356fa18bfc49fe97937f1d24198e7 Mon Sep 17 00:00:00 2001 From: Trevor Nichols Date: Fri, 25 Sep 2020 13:03:27 +1000 Subject: [PATCH 17/57] Implement Account SharedKey and SAS Authentication (#556) --- package.json | 2 +- .../BlobSharedKeyAuthenticator.ts | 2 +- .../IAccountSASSignatureValues.ts | 5 +- .../authentication/IBlobSASSignatureValues.ts | 5 +- src/blob/handlers/AppendBlobHandler.ts | 2 +- src/blob/handlers/BlobHandler.ts | 8 +- src/blob/handlers/BlockBlobHandler.ts | 6 +- src/blob/handlers/ContainerHandler.ts | 4 +- src/blob/handlers/PageBlobHandler.ts | 4 +- src/blob/persistence/LokiBlobMetadataStore.ts | 2 +- src/blob/persistence/SqlBlobMetadataStore.ts | 2 +- src/blob/utils/constants.ts | 5 - src/blob/utils/utils.ts | 109 ----- src/common/AccountDataStore.ts | 2 +- src/common/utils/constants.ts | 6 + src/common/utils/utils.ts | 109 +++++ .../IAccountSASSignatureValues.ts | 5 +- .../IQueueSASSignatureValues.ts | 5 +- .../QueueSharedKeyAuthenticator.ts | 10 +- src/queue/utils/constants.ts | 5 - src/queue/utils/utils.ts | 118 +---- src/table/TableRequestListenerFactory.ts | 30 +- src/table/TableServer.ts | 1 + .../authentication/AccountSASAuthenticator.ts | 314 ++++++++++++++ .../authentication/AccountSASPermissions.ts | 190 ++++++++ .../authentication/AccountSASResourceTypes.ts | 103 +++++ .../authentication/AccountSASServices.ts | 121 ++++++ .../IAccountSASSignatureValues.ts | 167 +++++++ .../authentication/IAuthenticationContext.ts | 3 + src/table/authentication/IAuthenticator.ts | 6 + src/table/authentication/IIPRange.ts | 37 ++ .../ITableSASSignatureValues.ts | 249 +++++++++++ .../OperationAccountSASPermission.ts | 205 +++++++++ .../OperationTableSASPermission.ts | 131 ++++++ .../authentication/TableSASAuthenticator.ts | 409 ++++++++++++++++++ .../authentication/TableSASPermissions.ts | 6 + .../TableSharedKeyAuthenticator.ts | 190 ++++++++ src/table/context/TableStorageContext.ts | 8 + src/table/errors/StorageErrorFactory.ts | 72 +++ src/table/handlers/TableHandler.ts | 2 +- .../AuthenticationMiddlewareFactory.ts | 60 +++ .../tableStorageContext.middleware.ts | 2 + .../persistence/LokiTableMetadataStore.ts | 2 +- src/table/utils/constants.ts | 10 +- src/table/utils/utils.ts | 16 +- tests/TableTestServerFactory.ts | 35 ++ tests/blob/apis/appendblob.test.ts | 2 +- tests/table/apis/table.entity.test.ts | 8 +- tests/table/apis/table.test.ts | 6 +- tests/table/sas.test.ts | 257 +++++++++++ tests/testutils.ts | 25 +- 51 files changed, 2792 insertions(+), 291 deletions(-) create mode 100644 src/table/authentication/AccountSASAuthenticator.ts create mode 100644 src/table/authentication/AccountSASPermissions.ts create mode 100644 src/table/authentication/AccountSASResourceTypes.ts create mode 100644 src/table/authentication/AccountSASServices.ts create mode 100644 src/table/authentication/IAccountSASSignatureValues.ts create mode 100644 src/table/authentication/IAuthenticationContext.ts create mode 100644 src/table/authentication/IAuthenticator.ts create mode 100644 src/table/authentication/IIPRange.ts create mode 100644 src/table/authentication/ITableSASSignatureValues.ts create mode 100644 src/table/authentication/OperationAccountSASPermission.ts create mode 100644 src/table/authentication/OperationTableSASPermission.ts create mode 100644 src/table/authentication/TableSASAuthenticator.ts create mode 100644 src/table/authentication/TableSASPermissions.ts create mode 100644 src/table/authentication/TableSharedKeyAuthenticator.ts create mode 100644 src/table/middleware/AuthenticationMiddlewareFactory.ts create mode 100644 tests/TableTestServerFactory.ts create mode 100644 tests/table/sas.test.ts diff --git a/package.json b/package.json index febb47862..3265d75f0 100644 --- a/package.json +++ b/package.json @@ -229,7 +229,7 @@ "test:blob:sql": "npm run lint && cross-env cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 AZURITE_TEST_DB=mysql://root:my-secret-pw@127.0.0.1:3306/azurite_blob_test mocha --compilers ts-node/register --no-timeouts --grep @sql --recursive tests/blob/*.test.ts tests/blob/**/*.test.ts", "test:blob:sql:ci": "npm run lint && cross-env cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 AZURITE_TEST_DB=mysql://root:my-secret-pw@127.0.0.1:13306/azurite_blob_test mocha --compilers ts-node/register --no-timeouts --grep @sql --recursive tests/blob/*.test.ts tests/blob/**/*.test.ts", "test:queue": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/queue/*.test.ts tests/queue/**/*.test.ts", - "test:table": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/table/apis/*.test.ts tests/table/apis/**/*.test.ts", + "test:table": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/table/*.test.ts tests/table/apis/*.test.ts tests/table/apis/**/*.test.ts", "clean": "rimraf dist typings *.log coverage __testspersistence__ temp __testsstorage__ .nyc_output debug.log *.vsix *.tgz", "clean:deep": "npm run clean && rimraf debug.log __*", "validate:npmpack:win": "npm install && npm run build && npm pack && cross-var npm install -g azurite-$npm_package_version.tgz && azurite -v && azurite-blob -v && azurite-queue -v", diff --git a/src/blob/authentication/BlobSharedKeyAuthenticator.ts b/src/blob/authentication/BlobSharedKeyAuthenticator.ts index 703dab0da..d59481e78 100644 --- a/src/blob/authentication/BlobSharedKeyAuthenticator.ts +++ b/src/blob/authentication/BlobSharedKeyAuthenticator.ts @@ -1,11 +1,11 @@ import IAccountDataStore from "../../common/IAccountDataStore"; import ILogger from "../../common/ILogger"; +import { computeHMACSHA256, getURLQueries } from "../../common/utils/utils"; import BlobStorageContext from "../context/BlobStorageContext"; import StorageErrorFactory from "../errors/StorageErrorFactory"; import Context from "../generated/Context"; import IRequest from "../generated/IRequest"; import { HeaderConstants } from "../utils/constants"; -import { computeHMACSHA256, getURLQueries } from "../utils/utils"; import IAuthenticator from "./IAuthenticator"; export default class BlobSharedKeyAuthenticator implements IAuthenticator { diff --git a/src/blob/authentication/IAccountSASSignatureValues.ts b/src/blob/authentication/IAccountSASSignatureValues.ts index 7651e2baa..7b0e6e48f 100644 --- a/src/blob/authentication/IAccountSASSignatureValues.ts +++ b/src/blob/authentication/IAccountSASSignatureValues.ts @@ -1,6 +1,9 @@ import { IIPRange } from "@azure/storage-blob"; -import { computeHMACSHA256, truncatedISO8061Date } from "../utils/utils"; +import { + computeHMACSHA256, + truncatedISO8061Date +} from "../../common/utils/utils"; import AccountSASPermissions from "./AccountSASPermissions"; import AccountSASResourceTypes from "./AccountSASResourceTypes"; import AccountSASServices from "./AccountSASServices"; diff --git a/src/blob/authentication/IBlobSASSignatureValues.ts b/src/blob/authentication/IBlobSASSignatureValues.ts index 969d70dc0..6f1985f28 100644 --- a/src/blob/authentication/IBlobSASSignatureValues.ts +++ b/src/blob/authentication/IBlobSASSignatureValues.ts @@ -1,4 +1,7 @@ -import { computeHMACSHA256, truncatedISO8061Date } from "../utils/utils"; +import { + computeHMACSHA256, + truncatedISO8061Date +} from "../../common/utils/utils"; import { BlobSASResourceType } from "./BlobSASResourceType"; import { SASProtocol } from "./IAccountSASSignatureValues"; import { IIPRange, ipRangeToString } from "./IIPRange"; diff --git a/src/blob/handlers/AppendBlobHandler.ts b/src/blob/handlers/AppendBlobHandler.ts index 77dd772ba..c366c1762 100644 --- a/src/blob/handlers/AppendBlobHandler.ts +++ b/src/blob/handlers/AppendBlobHandler.ts @@ -1,4 +1,5 @@ import { convertRawHeadersToMetadata } from "../../common/utils/utils"; +import { getMD5FromStream, newEtag } from "../../common/utils/utils"; import BlobStorageContext from "../context/BlobStorageContext"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; @@ -12,7 +13,6 @@ import { MAX_APPEND_BLOB_BLOCK_COUNT, MAX_APPEND_BLOB_BLOCK_SIZE } from "../utils/constants"; -import { getMD5FromStream, newEtag } from "../utils/utils"; import BaseHandler from "./BaseHandler"; export default class AppendBlobHandler extends BaseHandler diff --git a/src/blob/handlers/BlobHandler.ts b/src/blob/handlers/BlobHandler.ts index 575771ba0..7329ef80b 100644 --- a/src/blob/handlers/BlobHandler.ts +++ b/src/blob/handlers/BlobHandler.ts @@ -1,7 +1,10 @@ import { URL } from "url"; import IExtentStore from "../../common/persistence/IExtentStore"; -import { convertRawHeadersToMetadata } from "../../common/utils/utils"; +import { + convertRawHeadersToMetadata, + getMD5FromStream +} from "../../common/utils/utils"; import BlobStorageContext from "../context/BlobStorageContext"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; @@ -21,8 +24,7 @@ import { } from "../utils/constants"; import { deserializePageBlobRangeHeader, - deserializeRangeHeader, - getMD5FromStream + deserializeRangeHeader } from "../utils/utils"; import BaseHandler from "./BaseHandler"; import IPageBlobRangesManager from "./IPageBlobRangesManager"; diff --git a/src/blob/handlers/BlockBlobHandler.ts b/src/blob/handlers/BlockBlobHandler.ts index 55157bc44..5b7e21ddc 100644 --- a/src/blob/handlers/BlockBlobHandler.ts +++ b/src/blob/handlers/BlockBlobHandler.ts @@ -1,4 +1,9 @@ import { convertRawHeadersToMetadata } from "../../common/utils/utils"; +import { + getMD5FromStream, + getMD5FromString, + newEtag +} from "../../common/utils/utils"; import BlobStorageContext from "../context/BlobStorageContext"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; @@ -8,7 +13,6 @@ import IBlockBlobHandler from "../generated/handlers/IBlockBlobHandler"; import { parseXML } from "../generated/utils/xml"; import { BlobModel, BlockModel } from "../persistence/IBlobMetadataStore"; import { BLOB_API_VERSION } from "../utils/constants"; -import { getMD5FromStream, getMD5FromString, newEtag } from "../utils/utils"; import BaseHandler from "./BaseHandler"; /** diff --git a/src/blob/handlers/ContainerHandler.ts b/src/blob/handlers/ContainerHandler.ts index 0a15cd75e..0cbd05202 100644 --- a/src/blob/handlers/ContainerHandler.ts +++ b/src/blob/handlers/ContainerHandler.ts @@ -1,4 +1,4 @@ -import { convertRawHeadersToMetadata } from "../../common/utils/utils"; +import { convertRawHeadersToMetadata, newEtag } from "../../common/utils/utils"; import BlobStorageContext from "../context/BlobStorageContext"; import * as Models from "../generated/artifacts/models"; import Context from "../generated/Context"; @@ -9,7 +9,7 @@ import { EMULATOR_ACCOUNT_SKUNAME } from "../utils/constants"; import { DEFAULT_LIST_BLOBS_MAX_RESULTS } from "../utils/constants"; -import { newEtag, removeQuotationFromListBlobEtag } from "../utils/utils"; +import { removeQuotationFromListBlobEtag } from "../utils/utils"; import BaseHandler from "./BaseHandler"; /** diff --git a/src/blob/handlers/PageBlobHandler.ts b/src/blob/handlers/PageBlobHandler.ts index 1d6cf8e60..f91883f95 100644 --- a/src/blob/handlers/PageBlobHandler.ts +++ b/src/blob/handlers/PageBlobHandler.ts @@ -1,5 +1,5 @@ import IExtentStore from "../../common/persistence/IExtentStore"; -import { convertRawHeadersToMetadata } from "../../common/utils/utils"; +import { convertRawHeadersToMetadata, newEtag } from "../../common/utils/utils"; import BlobStorageContext from "../context/BlobStorageContext"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; @@ -13,7 +13,7 @@ import IBlobMetadataStore, { BlobModel } from "../persistence/IBlobMetadataStore"; import { BLOB_API_VERSION } from "../utils/constants"; -import { deserializePageBlobRangeHeader, newEtag } from "../utils/utils"; +import { deserializePageBlobRangeHeader } from "../utils/utils"; import BaseHandler from "./BaseHandler"; import IPageBlobRangesManager from "./IPageBlobRangesManager"; diff --git a/src/blob/persistence/LokiBlobMetadataStore.ts b/src/blob/persistence/LokiBlobMetadataStore.ts index a6c9ca14f..9dbbaec85 100644 --- a/src/blob/persistence/LokiBlobMetadataStore.ts +++ b/src/blob/persistence/LokiBlobMetadataStore.ts @@ -7,6 +7,7 @@ import { convertDateTimeStringMsTo7Digital, rimrafAsync } from "../../common/utils/utils"; +import { newEtag } from "../../common/utils/utils"; import { validateReadConditions } from "../conditions/ReadConditionalHeadersValidator"; import { validateSequenceNumberWriteConditions, @@ -32,7 +33,6 @@ import { DEFAULT_LIST_CONTAINERS_MAX_RESULTS, MAX_APPEND_BLOB_BLOCK_COUNT } from "../utils/constants"; -import { newEtag } from "../utils/utils"; import BlobReferredExtentsAsyncIterator from "./BlobReferredExtentsAsyncIterator"; import IBlobMetadataStore, { AcquireBlobLeaseResponse, diff --git a/src/blob/persistence/SqlBlobMetadataStore.ts b/src/blob/persistence/SqlBlobMetadataStore.ts index 8192a734a..e832f7e86 100644 --- a/src/blob/persistence/SqlBlobMetadataStore.ts +++ b/src/blob/persistence/SqlBlobMetadataStore.ts @@ -15,6 +15,7 @@ import { DEFAULT_SQL_COLLATE } from "../../common/utils/constants"; import { convertDateTimeStringMsTo7Digital } from "../../common/utils/utils"; +import { newEtag } from "../../common/utils/utils"; import { validateReadConditions } from "../conditions/ReadConditionalHeadersValidator"; import { validateWriteConditions } from "../conditions/WriteConditionalHeadersValidator"; import StorageErrorFactory from "../errors/StorageErrorFactory"; @@ -35,7 +36,6 @@ import { DEFAULT_LIST_BLOBS_MAX_RESULTS, DEFAULT_LIST_CONTAINERS_MAX_RESULTS } from "../utils/constants"; -import { newEtag } from "../utils/utils"; import BlobReferredExtentsAsyncIterator from "./BlobReferredExtentsAsyncIterator"; import IBlobMetadataStore, { AcquireBlobLeaseResponse, diff --git a/src/blob/utils/constants.ts b/src/blob/utils/constants.ts index 3d87d453f..a2ff8899c 100644 --- a/src/blob/utils/constants.ts +++ b/src/blob/utils/constants.ts @@ -20,11 +20,6 @@ export const DEFAULT_CONTEXT_PATH = "azurite_blob_context"; export const LOGGER_CONFIGS = {}; export const DEFAULT_GC_INTERVAL_MS = 10 * 60 * 1000; export const DEFAULT_WRITE_CONCURRENCY_PER_LOCATION = 50; -export const EMULATOR_ACCOUNT_NAME = "devstoreaccount1"; -export const EMULATOR_ACCOUNT_KEY = Buffer.from( - "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", - "base64" -); export const EMULATOR_ACCOUNT_SKUNAME = Models.SkuName.StandardRAGRS; export const EMULATOR_ACCOUNT_KIND = Models.AccountKind.StorageV2; diff --git a/src/blob/utils/utils.ts b/src/blob/utils/utils.ts index 2dde4f3d3..576069252 100644 --- a/src/blob/utils/utils.ts +++ b/src/blob/utils/utils.ts @@ -1,21 +1,6 @@ -import { createHash, createHmac } from "crypto"; import { createWriteStream, PathLike } from "fs"; -import { parse } from "url"; import StorageErrorFactory from "../errors/StorageErrorFactory"; -/** - * Generates a hash signature for an HTTP request or for a SAS. - * - * @param {string} stringToSign - * @param {key} key - * @returns {string} - */ -export function computeHMACSHA256(stringToSign: string, key: Buffer): string { - return createHmac("sha256", key) - .update(stringToSign, "utf8") - .digest("base64"); -} - export function checkApiVersion( inputApiVersion: string, validApiVersions: Array, @@ -29,40 +14,6 @@ export function checkApiVersion( } } -/** - * Rounds a date off to seconds. - * - * @export - * @param {Date} date - * @param {boolean} [withMilliseconds=true] If true, YYYY-MM-DDThh:mm:ss.fffffffZ will be returned; - * If false, YYYY-MM-DDThh:mm:ssZ will be returned. - * @returns {string} Date string in ISO8061 format, with or without 7 milliseconds component - */ -export function truncatedISO8061Date( - date: Date, - withMilliseconds: boolean = true -): string { - // Date.toISOString() will return like "2018-10-29T06:34:36.139Z" - const dateString = date.toISOString(); - - return withMilliseconds - ? dateString.substring(0, dateString.length - 1) + "0000" + "Z" - : dateString.substring(0, dateString.length - 5) + "Z"; -} - -export function newEtag(): string { - // Etag should match ^"0x[A-F0-9]{15,}"$ - // Date().getTime().toString(16) only has 11 digital - // so multiply a number between 70000-100000, can get a 16 based 15+ digital number - return ( - '"0x' + - (new Date().getTime() * Math.round(Math.random() * 30000 + 70000)) - .toString(16) - .toUpperCase() + - '"' - ); -} - export async function streamToLocalFile( stream: NodeJS.ReadableStream, path: PathLike @@ -78,66 +29,6 @@ export async function streamToLocalFile( }); } -export async function getMD5FromStream( - stream: NodeJS.ReadableStream -): Promise { - const hash = createHash("md5"); - return new Promise((resolve, reject) => { - stream - .on("data", data => { - hash.update(data); - }) - .on("end", () => { - resolve(hash.digest()); - }) - .on("error", err => { - reject(err); - }); - }); -} - -export async function getMD5FromString(text: string): Promise { - return createHash("md5") - .update(text) - .digest(); -} - -/** - * Get URL query key value pairs from an URL string. - * - * @export - * @param {string} url - * @returns {{[key: string]: string}} - */ -export function getURLQueries(url: string): { [key: string]: string } { - let queryString = parse(url).query; - if (!queryString) { - return {}; - } - - queryString = queryString.trim(); - queryString = queryString.startsWith("?") - ? queryString.substr(1) - : queryString; - - let querySubStrings: string[] = queryString.split("&"); - querySubStrings = querySubStrings.filter((value: string) => { - const indexOfEqual = value.indexOf("="); - const lastIndexOfEqual = value.lastIndexOf("="); - return indexOfEqual > 0 && indexOfEqual === lastIndexOfEqual; - }); - - const queries: { [key: string]: string } = {}; - for (const querySubString of querySubStrings) { - const splitResults = querySubString.split("="); - const key: string = splitResults[0]; - const value: string = splitResults[1]; - queries[key] = value; - } - - return queries; -} - /** * Default range value [0, Infinite] will be returned if all parameters not provided. * diff --git a/src/common/AccountDataStore.ts b/src/common/AccountDataStore.ts index 8a80c5ee0..65a88eec9 100644 --- a/src/common/AccountDataStore.ts +++ b/src/common/AccountDataStore.ts @@ -1,7 +1,7 @@ import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME -} from "../blob/utils/constants"; +} from "../common/utils/constants"; import ILogger from "../queue/generated/utils/ILogger"; import IAccountDataStore, { IAccountProperties } from "./IAccountDataStore"; import { diff --git a/src/common/utils/constants.ts b/src/common/utils/constants.ts index 68d826ebd..4deb20008 100644 --- a/src/common/utils/constants.ts +++ b/src/common/utils/constants.ts @@ -47,3 +47,9 @@ export const VALID_ISSUE_PREFIXES = [ "https://sts.chinacloudapi.cn/", "https://sts.windows-ppe.net" ]; + +export const EMULATOR_ACCOUNT_NAME = "devstoreaccount1"; +export const EMULATOR_ACCOUNT_KEY = Buffer.from( + "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", + "base64" +); diff --git a/src/common/utils/utils.ts b/src/common/utils/utils.ts index 73ef33bf0..51b2ab46f 100644 --- a/src/common/utils/utils.ts +++ b/src/common/utils/utils.ts @@ -1,4 +1,6 @@ +import { createHash, createHmac } from "crypto"; import rimraf = require("rimraf"); +import { parse } from "url"; import { promisify } from "util"; // LokiFsStructuredAdapter @@ -44,3 +46,110 @@ export function convertRawHeadersToMetadata( return isEmpty ? undefined : res; } + +export function newEtag(): string { + // Etag should match ^"0x[A-F0-9]{15,}"$ + // Date().getTime().toString(16) only has 11 digital + // so multiply a number between 70000-100000, can get a 16 based 15+ digital number + return ( + '"0x' + + (new Date().getTime() * Math.round(Math.random() * 30000 + 70000)) + .toString(16) + .toUpperCase() + + '"' + ); +} + +/** + * Generates a hash signature for an HTTP request or for a SAS. + * + * @param {string} stringToSign + * @param {key} key + * @returns {string} + */ +export function computeHMACSHA256(stringToSign: string, key: Buffer): string { + return createHmac("sha256", key) + .update(stringToSign, "utf8") + .digest("base64"); +} + +/** + * Rounds a date off to seconds. + * + * @export + * @param {Date} date + * @param {boolean} [withMilliseconds=true] If true, YYYY-MM-DDThh:mm:ss.fffffffZ will be returned; + * If false, YYYY-MM-DDThh:mm:ssZ will be returned. + * @returns {string} Date string in ISO8061 format, with or without 7 milliseconds component + */ +export function truncatedISO8061Date( + date: Date, + withMilliseconds: boolean = true +): string { + // Date.toISOString() will return like "2018-10-29T06:34:36.139Z" + const dateString = date.toISOString(); + + return withMilliseconds + ? dateString.substring(0, dateString.length - 1) + "0000" + "Z" + : dateString.substring(0, dateString.length - 5) + "Z"; +} + +/** + * Get URL query key value pairs from an URL string. + * + * @export + * @param {string} url + * @returns {{[key: string]: string}} + */ +export function getURLQueries(url: string): { [key: string]: string } { + let queryString = parse(url).query; + if (!queryString) { + return {}; + } + + queryString = queryString.trim(); + queryString = queryString.startsWith("?") + ? queryString.substr(1) + : queryString; + + let querySubStrings: string[] = queryString.split("&"); + querySubStrings = querySubStrings.filter((value: string) => { + const indexOfEqual = value.indexOf("="); + const lastIndexOfEqual = value.lastIndexOf("="); + return indexOfEqual > 0 && indexOfEqual === lastIndexOfEqual; + }); + + const queries: { [key: string]: string } = {}; + for (const querySubString of querySubStrings) { + const splitResults = querySubString.split("="); + const key: string = splitResults[0]; + const value: string = splitResults[1]; + queries[key] = value; + } + + return queries; +} + +export async function getMD5FromString(text: string): Promise { + return createHash("md5") + .update(text) + .digest(); +} + +export async function getMD5FromStream( + stream: NodeJS.ReadableStream +): Promise { + const hash = createHash("md5"); + return new Promise((resolve, reject) => { + stream + .on("data", data => { + hash.update(data); + }) + .on("end", () => { + resolve(hash.digest()); + }) + .on("error", err => { + reject(err); + }); + }); +} diff --git a/src/queue/authentication/IAccountSASSignatureValues.ts b/src/queue/authentication/IAccountSASSignatureValues.ts index 7651e2baa..7b0e6e48f 100644 --- a/src/queue/authentication/IAccountSASSignatureValues.ts +++ b/src/queue/authentication/IAccountSASSignatureValues.ts @@ -1,6 +1,9 @@ import { IIPRange } from "@azure/storage-blob"; -import { computeHMACSHA256, truncatedISO8061Date } from "../utils/utils"; +import { + computeHMACSHA256, + truncatedISO8061Date +} from "../../common/utils/utils"; import AccountSASPermissions from "./AccountSASPermissions"; import AccountSASResourceTypes from "./AccountSASResourceTypes"; import AccountSASServices from "./AccountSASServices"; diff --git a/src/queue/authentication/IQueueSASSignatureValues.ts b/src/queue/authentication/IQueueSASSignatureValues.ts index 388d73072..d9e796dcd 100644 --- a/src/queue/authentication/IQueueSASSignatureValues.ts +++ b/src/queue/authentication/IQueueSASSignatureValues.ts @@ -1,4 +1,7 @@ -import { computeHMACSHA256, truncatedISO8061Date } from "../utils/utils"; +import { + computeHMACSHA256, + truncatedISO8061Date +} from "../../common/utils/utils"; import { SASProtocol } from "./IAccountSASSignatureValues"; import { IIPRange, ipRangeToString } from "./IIPRange"; diff --git a/src/queue/authentication/QueueSharedKeyAuthenticator.ts b/src/queue/authentication/QueueSharedKeyAuthenticator.ts index 25b818049..06d95468e 100644 --- a/src/queue/authentication/QueueSharedKeyAuthenticator.ts +++ b/src/queue/authentication/QueueSharedKeyAuthenticator.ts @@ -1,11 +1,11 @@ import IAccountDataStore from "../../common/IAccountDataStore"; import ILogger from "../../common/ILogger"; +import { computeHMACSHA256, getURLQueries } from "../../common/utils/utils"; import QueueStorageContext from "../context/QueueStorageContext"; import StorageErrorFactory from "../errors/StorageErrorFactory"; import Context from "../generated/Context"; import IRequest from "../generated/IRequest"; import { HeaderConstants } from "../utils/constants"; -import { computeHMACSHA256, getURLQueries } from "../utils/utils"; import IAuthenticator from "./IAuthenticator"; export default class QueueSharedKeyAuthenticator implements IAuthenticator { @@ -180,11 +180,9 @@ export default class QueueSharedKeyAuthenticator implements IAuthenticator { .startsWith(HeaderConstants.PREFIX_FOR_STORAGE); }); - headersArray.sort( - (a, b): number => { - return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); - } - ); + headersArray.sort((a, b): number => { + return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); + }); let canonicalizedHeadersStringToSign: string = ""; headersArray.forEach(header => { diff --git a/src/queue/utils/constants.ts b/src/queue/utils/constants.ts index c910f4d18..bfa9b292a 100644 --- a/src/queue/utils/constants.ts +++ b/src/queue/utils/constants.ts @@ -16,11 +16,6 @@ export const DEFAULT_ENABLE_ACCESS_LOG = true; export const DEFAULT_QUEUE_CONTEXT_PATH = "azurite_queue_context"; export const LOGGER_CONFIGS = {}; export const DEFAULT_GC_INTERVAL_MS = 60 * 1000; -export const EMULATOR_ACCOUNT_NAME = "devstoreaccount1"; -export const EMULATOR_ACCOUNT_KEY = Buffer.from( - "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==", - "base64" -); export const NEVER_EXPIRE_DATE = new Date("9999-12-31T23:59:59.999Z"); export const QUEUE_SERVICE_PERMISSION = "raup"; export const LIST_QUEUE_MAXRESSULTS_MIN = 1; diff --git a/src/queue/utils/utils.ts b/src/queue/utils/utils.ts index 9ae567b83..f3ac92293 100644 --- a/src/queue/utils/utils.ts +++ b/src/queue/utils/utils.ts @@ -1,23 +1,8 @@ -import { createHash, createHmac, randomBytes } from "crypto"; -import etag from "etag"; -import { createWriteStream, PathLike } from "fs"; -import { parse } from "url"; +import { randomBytes } from "crypto"; + import * as xml2js from "xml2js"; import StorageErrorFactory from "../errors/StorageErrorFactory"; -/** - * Generates a hash signature for an HTTP request or for a SAS. - * - * @param {string} stringToSign - * @param {key} key - * @returns {string} - */ -export function computeHMACSHA256(stringToSign: string, key: Buffer): string { - return createHmac("sha256", key) - .update(stringToSign, "utf8") - .digest("base64"); -} - export function checkApiVersion( inputApiVersion: string, validApiVersions: Array, @@ -31,105 +16,6 @@ export function checkApiVersion( } } -/** - * Rounds a date off to seconds. - * - * @export - * @param {Date} date - * @param {boolean} [withMilliseconds=true] If true, YYYY-MM-DDThh:mm:ss.fffffffZ will be returned; - * If false, YYYY-MM-DDThh:mm:ssZ will be returned. - * @returns {string} Date string in ISO8061 format, with or without 7 milliseconds component - */ -export function truncatedISO8061Date( - date: Date, - withMilliseconds: boolean = true -): string { - // Date.toISOString() will return like "2018-10-29T06:34:36.139Z" - const dateString = date.toISOString(); - - return withMilliseconds - ? dateString.substring(0, dateString.length - 1) + "0000" + "Z" - : dateString.substring(0, dateString.length - 5) + "Z"; -} - -// TODO: Align eTag with Azure Storage Service -export function newEtag(): string { - return etag(`${new Date().getTime()}`); -} - -export async function streamToLocalFile( - stream: NodeJS.ReadableStream, - path: PathLike -): Promise { - return new Promise((resolve, reject) => { - const writeStream = createWriteStream(path); - stream - .on("error", reject) - // .on("end", resolve) - .pipe(writeStream) - .on("close", resolve) - .on("error", reject); - }); -} - -export async function getMD5FromStream( - stream: NodeJS.ReadableStream -): Promise { - const hash = createHash("md5"); - return new Promise((resolve, reject) => { - stream - .on("data", data => { - hash.update(data); - }) - .on("end", () => { - resolve(hash.digest()); - }) - .on("error", reject); - }); -} - -export async function getMD5FromString(text: string): Promise { - return createHash("md5") - .update(text) - .digest(); -} - -/** - * Get URL query key value pairs from an URL string. - * - * @export - * @param {string} url - * @returns {{[key: string]: string}} - */ -export function getURLQueries(url: string): { [key: string]: string } { - let queryString = parse(url).query; - if (!queryString) { - return {}; - } - - queryString = queryString.trim(); - queryString = queryString.startsWith("?") - ? queryString.substr(1) - : queryString; - - let querySubStrings: string[] = queryString.split("&"); - querySubStrings = querySubStrings.filter((value: string) => { - const indexOfEqual = value.indexOf("="); - const lastIndexOfEqual = value.lastIndexOf("="); - return indexOfEqual > 0 && indexOfEqual === lastIndexOfEqual; - }); - - const queries: { [key: string]: string } = {}; - for (const querySubString of querySubStrings) { - const splitResults = querySubString.split("="); - const key: string = splitResults[0]; - const value: string = splitResults[1]; - queries[key] = value; - } - - return queries; -} - /** * Default range value [0, Infinite] will be returned if all parameters not provided. * diff --git a/src/table/TableRequestListenerFactory.ts b/src/table/TableRequestListenerFactory.ts index 0dc4f4628..9497a113b 100644 --- a/src/table/TableRequestListenerFactory.ts +++ b/src/table/TableRequestListenerFactory.ts @@ -1,10 +1,12 @@ +import { OperationSpec } from "@azure/ms-rest-js/es/lib/operationSpec"; import express from "express"; import { RequestListener } from "http"; - -import { OperationSpec } from "@azure/ms-rest-js/es/lib/operationSpec"; - +import IAccountDataStore from "../common/IAccountDataStore"; import IRequestListenerFactory from "../common/IRequestListenerFactory"; import logger from "../common/Logger"; +import AccountSASAuthenticator from "./authentication/AccountSASAuthenticator"; +import IAuthenticator from "./authentication/IAuthenticator"; +import TableSASAuthenticator from "./authentication/TableSASAuthenticator"; import { Operation } from "./generated/artifacts/operation"; import Specifications from "./generated/artifacts/specifications"; import ExpressMiddlewareFactory from "./generated/ExpressMiddlewareFactory"; @@ -12,11 +14,13 @@ import IHandlers from "./generated/handlers/IHandlers"; import MiddlewareFactory from "./generated/MiddlewareFactory"; import ServiceHandler from "./handlers/ServiceHandler"; import TableHandler from "./handlers/TableHandler"; +import AuthenticationMiddlewareFactory from "./middleware/AuthenticationMiddlewareFactory"; import createTableStorageContextMiddleware from "./middleware/tableStorageContext.middleware"; import ITableMetadataStore from "./persistence/ITableMetadataStore"; import { DEFAULT_TABLE_CONTEXT_PATH } from "./utils/constants"; import morgan = require("morgan"); +import TableSharedKeyAuthenticator from "./authentication/TableSharedKeyAuthenticator"; /** * Default RequestListenerFactory based on express framework. * @@ -31,6 +35,7 @@ export default class TableRequestListenerFactory implements IRequestListenerFactory { public constructor( private readonly metadataStore: ITableMetadataStore, + private readonly accountDataStore: IAccountDataStore, private readonly enableAccessLog: boolean, private readonly accessLogWriteStream?: NodeJS.WritableStream, private readonly skipApiVersionCheck?: boolean @@ -100,6 +105,25 @@ export default class TableRequestListenerFactory // Dispatch incoming HTTP request to specific operation app.use(middlewareFactory.createDispatchMiddleware()); + // AuthN middleware, like shared key auth or SAS auth + const authenticationMiddlewareFactory = new AuthenticationMiddlewareFactory( + logger + ); + const authenticators: IAuthenticator[] = [ + new TableSharedKeyAuthenticator(this.accountDataStore, logger), + new AccountSASAuthenticator(this.accountDataStore, logger), + new TableSASAuthenticator( + this.accountDataStore, + this.metadataStore, + logger + ) + ]; + app.use( + authenticationMiddlewareFactory.createAuthenticationMiddleware( + authenticators + ) + ); + // Generated, will do basic validation defined in swagger app.use(middlewareFactory.createDeserializerMiddleware()); diff --git a/src/table/TableServer.ts b/src/table/TableServer.ts index b480e193a..cc91d71f4 100644 --- a/src/table/TableServer.ts +++ b/src/table/TableServer.ts @@ -57,6 +57,7 @@ export default class TableServer extends ServerBase { // Here we use express request listener and register table handler const requestListenerFactory: IRequestListenerFactory = new TableRequestListenerFactory( metadataStore, + accountDataStore, configuration.enableAccessLog, // Access log includes every handled HTTP request configuration.accessLogWriteStream, configuration.skipApiVersionCheck diff --git a/src/table/authentication/AccountSASAuthenticator.ts b/src/table/authentication/AccountSASAuthenticator.ts new file mode 100644 index 000000000..6c212969f --- /dev/null +++ b/src/table/authentication/AccountSASAuthenticator.ts @@ -0,0 +1,314 @@ +import IAccountDataStore from "../../common/IAccountDataStore"; +import ILogger from "../../common/ILogger"; +import StorageErrorFactory from "../errors/StorageErrorFactory"; +import Operation from "../generated/artifacts/operation"; +import Context from "../generated/Context"; +import IRequest from "../generated/IRequest"; +import { + generateAccountSASSignature, + IAccountSASSignatureValues +} from "./IAccountSASSignatureValues"; +import IAuthenticator from "./IAuthenticator"; +import OPERATION_ACCOUNT_SAS_PERMISSIONS from "./OperationAccountSASPermission"; + +export default class AccountSASAuthenticator implements IAuthenticator { + public constructor( + private readonly accountDataStore: IAccountDataStore, + private readonly logger: ILogger + ) {} + + public async validate( + req: IRequest, + context: Context + ): Promise { + this.logger.info( + `AccountSASAuthenticator:validate() Start validation against account Shared Access Signature pattern.`, + context.contextID + ); + + this.logger.debug( + "AccountSASAuthenticator:validate() Getting account properties...", + context.contextID + ); + + const account: string = context.context.account; + const tableName: string | undefined = context.context.table; + this.logger.debug( + // tslint:disable-next-line:max-line-length + `AccountSASAuthenticator:validate() Retrieved account name from context: ${account}, table: ${tableName}`, + context.contextID + ); + + // TODO: Make following async + const accountProperties = this.accountDataStore.getAccount(account); + if (accountProperties === undefined) { + throw StorageErrorFactory.getInvalidOperation( + context.contextID!, + "Invalid storage account." + ); + } + this.logger.debug( + "AccountSASAuthenticator:validate() Got account properties successfully.", + context.contextID + ); + + const signature = this.decodeIfExist(req.getQuery("sig")); + this.logger.debug( + `AccountSASAuthenticator:validate() Retrieved signature from URL parameter sig: ${signature}`, + context.contextID + ); + + const values = this.getAccountSASSignatureValuesFromRequest(req); + if (values === undefined) { + this.logger.info( + `AccountSASAuthenticator:validate() Failed to get valid account SAS values from request.`, + context.contextID + ); + return false; + } + this.logger.debug( + `AccountSASAuthenticator:validate() Successfully got valid account SAS values from request. ${JSON.stringify( + values + )}`, + context.contextID + ); + + this.logger.info( + `AccountSASAuthenticator:validate() Validate signature based account key1.`, + context.contextID + ); + const [sig1, stringToSign1] = generateAccountSASSignature( + values, + account, + accountProperties.key1 + ); + this.logger.debug( + `AccountSASAuthenticator:validate() String to sign is: ${JSON.stringify( + stringToSign1 + )}`, + context.contextID! + ); + this.logger.debug( + `AccountSASAuthenticator:validate() Calculated signature is: ${sig1}`, + context.contextID! + ); + + const sig1Pass = sig1 === signature; + this.logger.info( + `AccountSASAuthenticator:validate() Signature based on key1 validation ${ + sig1Pass ? "passed" : "failed" + }.`, + context.contextID + ); + + if (accountProperties.key2 !== undefined) { + this.logger.info( + `AccountSASAuthenticator:validate() Account key2 is not empty, validate signature based account key2.`, + context.contextID + ); + const [sig2, stringToSign2] = generateAccountSASSignature( + values, + account, + accountProperties.key2 + ); + this.logger.debug( + `AccountSASAuthenticator:validate() String to sign is: ${JSON.stringify( + stringToSign2 + )}`, + context.contextID! + ); + this.logger.debug( + `AccountSASAuthenticator:validate() Calculated signature is: ${sig2}`, + context.contextID! + ); + + const sig2Pass = sig2 !== signature; + this.logger.info( + `AccountSASAuthenticator:validate() Signature based on key2 validation ${ + sig2Pass ? "passed" : "failed" + }.`, + context.contextID + ); + + if (!sig2Pass && !sig1Pass) { + this.logger.info( + `AccountSASAuthenticator:validate() Validate signature based account key1 and key2 failed.`, + context.contextID + ); + return false; + } + } else { + if (!sig1Pass) { + return false; + } + } + + // When signature validation passes, we enforce account SAS validation + // Any validation errors will stop this request immediately + + this.logger.info( + `AccountSASAuthenticator:validate() Validate start and expiry time.`, + context.contextID + ); + if (!this.validateTime(values.expiryTime, values.startTime)) { + this.logger.info( + `AccountSASAuthenticator:validate() Validate start and expiry failed.`, + context.contextID + ); + throw StorageErrorFactory.getAuthorizationFailure(context.contextID!); + } + + this.logger.info( + `AccountSASAuthenticator:validate() Validate IP range.`, + context.contextID + ); + if (!this.validateIPRange()) { + this.logger.info( + `AccountSASAuthenticator:validate() Validate IP range failed.`, + context.contextID + ); + throw StorageErrorFactory.getAuthorizationSourceIPMismatch( + context.contextID! + ); + } + + this.logger.info( + `AccountSASAuthenticator:validate() Validate request protocol.`, + context.contextID + ); + if (!this.validateProtocol(values.protocol, req.getProtocol())) { + this.logger.info( + `AccountSASAuthenticator:validate() Validate protocol failed.`, + context.contextID + ); + throw StorageErrorFactory.getAuthorizationProtocolMismatch( + context.contextID! + ); + } + + const operation = context.operation; + if (operation === undefined) { + throw new Error( + // tslint:disable-next-line:max-line-length + `AccountSASAuthenticator:validate() operation shouldn't be undefined. Please make sure DispatchMiddleware is hooked before authentication related middleware.` + ); + } + + const accountSASPermission = OPERATION_ACCOUNT_SAS_PERMISSIONS.get( + operation + ); + this.logger.debug( + `AccountSASAuthenticator:validate() Got permission requirements for operation ${ + Operation[operation] + } - ${JSON.stringify(accountSASPermission)}`, + context.contextID + ); + if (accountSASPermission === undefined) { + throw new Error( + // tslint:disable-next-line:max-line-length + `AccountSASAuthenticator:validate() OPERATION_ACCOUNT_SAS_PERMISSIONS doesn't have configuration for operation ${Operation[operation]}'s account SAS permission.` + ); + } + + if (!accountSASPermission.validateServices(values.services)) { + throw StorageErrorFactory.getAuthorizationServiceMismatch( + context.contextID! + ); + } + + if (!accountSASPermission.validateResourceTypes(values.resourceTypes)) { + throw StorageErrorFactory.getAuthorizationResourceTypeMismatch( + context.contextID! + ); + } + + if (!accountSASPermission.validatePermissions(values.permissions)) { + throw StorageErrorFactory.getAuthorizationPermissionMismatch( + context.contextID! + ); + } + + this.logger.info( + `AccountSASAuthenticator:validate() Account SAS validation successfully.`, + context.contextID + ); + + return true; + } + + private getAccountSASSignatureValuesFromRequest( + req: IRequest + ): IAccountSASSignatureValues | undefined { + const version = this.decodeIfExist(req.getQuery("sv")); + const services = this.decodeIfExist(req.getQuery("ss")); + const resourceTypes = this.decodeIfExist(req.getQuery("srt")); + const protocol = this.decodeIfExist(req.getQuery("spr")); + const startTime = this.decodeIfExist(req.getQuery("st")); + const expiryTime = this.decodeIfExist(req.getQuery("se")); + const ipRange = this.decodeIfExist(req.getQuery("sip")); + const permissions = this.decodeIfExist(req.getQuery("sp")); + const signature = this.decodeIfExist(req.getQuery("sig")); + + if ( + version === undefined || + expiryTime === undefined || + permissions === undefined || + services === undefined || + resourceTypes === undefined || + signature === undefined + ) { + return undefined; + } + + const accountSASValues: IAccountSASSignatureValues = { + version, + protocol, + startTime, + expiryTime, + permissions, + ipRange, + services, + resourceTypes + }; + + return accountSASValues; + } + + private validateTime(expiry: Date | string, start?: Date | string): boolean { + const expiryTime = new Date(expiry); + const now = new Date(); + + if (now > expiryTime) { + return false; + } + + if (start !== undefined) { + const startTime = new Date(start); + if (now < startTime) { + return false; + } + } + + return true; + } + + private validateIPRange(): boolean { + // TODO: Emulator doesn't validate IP Address + return true; + } + + private validateProtocol( + sasProtocol: string = "https,http", + requestProtocol: string + ): boolean { + if (sasProtocol.includes(",")) { + return true; + } else { + return sasProtocol.toLowerCase() === requestProtocol; + } + } + + private decodeIfExist(value?: string): string | undefined { + return value === undefined ? value : decodeURIComponent(value); + } +} diff --git a/src/table/authentication/AccountSASPermissions.ts b/src/table/authentication/AccountSASPermissions.ts new file mode 100644 index 000000000..d967cb49d --- /dev/null +++ b/src/table/authentication/AccountSASPermissions.ts @@ -0,0 +1,190 @@ +export enum AccountSASPermission { + Read = "r", + Write = "w", + Delete = "d", + List = "l", + Add = "a", + Create = "c", + Update = "u", + Process = "p" +} + +/** + * This is a helper class to construct a string representing the permissions granted by an AccountSAS. Setting a value + * to true means that any SAS which uses these permissions will grant permissions for that operation. Once all the + * values are set, this should be serialized with toString and set as the permissions field on an + * {@link AccountSASSignatureValues} object. It is possible to construct the permissions string without this class, but + * the order of the permissions is particular and this class guarantees correctness. + * + * @export + * @class AccountSASPermissions + */ +export default class AccountSASPermissions { + /** + * Parse initializes the AccountSASPermissions fields from a string. + * + * @static + * @param {string} permissions + * @returns {AccountSASPermissions} + * @memberof AccountSASPermissions + */ + public static parse(permissions: string): AccountSASPermissions { + const accountSASPermissions = new AccountSASPermissions(); + + for (const c of permissions) { + switch (c) { + case AccountSASPermission.Read: + if (accountSASPermissions.read) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASPermissions.read = true; + break; + case AccountSASPermission.Write: + if (accountSASPermissions.write) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASPermissions.write = true; + break; + case AccountSASPermission.Delete: + if (accountSASPermissions.delete) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASPermissions.delete = true; + break; + case AccountSASPermission.List: + if (accountSASPermissions.list) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASPermissions.list = true; + break; + case AccountSASPermission.Add: + if (accountSASPermissions.add) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASPermissions.add = true; + break; + case AccountSASPermission.Create: + if (accountSASPermissions.create) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASPermissions.create = true; + break; + case AccountSASPermission.Update: + if (accountSASPermissions.update) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASPermissions.update = true; + break; + default: + throw new RangeError(`Invalid permission character: ${c}`); + } + } + + return accountSASPermissions; + } + + /** + * Permission to read resources and list tables granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public read: boolean = false; + + /** + * Permission to write resources granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public write: boolean = false; + + /** + * Permission to delete tables granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public delete: boolean = false; + + /** + * Permission to list tables granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public list: boolean = false; + + /** + * Permission to add table entities granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public add: boolean = false; + + /** + * Permission to create tables. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public create: boolean = false; + + /** + * Permissions to update table entities granted. + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public update: boolean = false; + + /** + * Permissions to process, which doesn't apply for tables + * + * @type {boolean} + * @memberof AccountSASPermissions + */ + public process: boolean = false; + + /** + * Produces the SAS permissions string for an Azure Storage account. + * Call this method to set AccountSASSignatureValues Permissions field. + * + * Using this method will guarantee the resource types are in + * an order accepted by the service. + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + * + * @returns {string} + * @memberof AccountSASPermissions + */ + public toString(): string { + // The order of the characters should be as specified here to ensure correctness: + // https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + // Use a string array instead of string concatenating += operator for performance + const permissions: string[] = []; + if (this.read) { + permissions.push(AccountSASPermission.Read); + } + if (this.write) { + permissions.push(AccountSASPermission.Write); + } + if (this.delete) { + permissions.push(AccountSASPermission.Delete); + } + if (this.list) { + permissions.push(AccountSASPermission.List); + } + if (this.add) { + permissions.push(AccountSASPermission.Add); + } + if (this.create) { + permissions.push(AccountSASPermission.Create); + } + if (this.update) { + permissions.push(AccountSASPermission.Update); + } + return permissions.join(""); + } +} diff --git a/src/table/authentication/AccountSASResourceTypes.ts b/src/table/authentication/AccountSASResourceTypes.ts new file mode 100644 index 000000000..06a50996c --- /dev/null +++ b/src/table/authentication/AccountSASResourceTypes.ts @@ -0,0 +1,103 @@ +export enum AccountSASResourceType { + Service = "s", + Container = "c", + Object = "o" +} + +/** + * This is a helper class to construct a string representing the resources accessible by an AccountSAS. Setting a value + * to true means that any SAS which uses these permissions will grant access to that resource type. Once all the + * values are set, this should be serialized with toString and set as the resources field on an + * {@link AccountSASSignatureValues} object. It is possible to construct the resources string without this class, but + * the order of the resources is particular and this class guarantees correctness. + * + * @export + * @class AccountSASResourceTypes + */ +export default class AccountSASResourceTypes { + /** + * Creates an {@link AccountSASResourceType} from the specified resource types string. This method will throw an + * Error if it encounters a character that does not correspond to a valid resource type. + * + * @static + * @param {string} resourceTypes + * @returns {AccountSASResourceTypes} + * @memberof AccountSASResourceTypes + */ + public static parse(resourceTypes: string): AccountSASResourceTypes { + const accountSASResourceTypes = new AccountSASResourceTypes(); + + for (const c of resourceTypes) { + switch (c) { + case AccountSASResourceType.Service: + if (accountSASResourceTypes.service) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASResourceTypes.service = true; + break; + case AccountSASResourceType.Container: + if (accountSASResourceTypes.container) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASResourceTypes.container = true; + break; + case AccountSASResourceType.Object: + if (accountSASResourceTypes.object) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASResourceTypes.object = true; + break; + default: + throw new RangeError(`Invalid resource type: ${c}`); + } + } + + return accountSASResourceTypes; + } + + /** + * Permission to access service level APIs granted. + * + * @type {boolean} + * @memberof AccountSASResourceTypes + */ + public service: boolean = false; + + /** + * Permission to access container level APIs (Blob Containers, Tables, Queues, File Shares) granted. + * + * @type {boolean} + * @memberof AccountSASResourceTypes + */ + public container: boolean = false; + + /** + * Permission to access object level APIs (Blobs, Table Entities, Queue Messages, Files) granted. + * + * @type {boolean} + * @memberof AccountSASResourceTypes + */ + public object: boolean = false; + + /** + * Converts the given resource types to a string. + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + * + * @returns {string} + * @memberof AccountSASResourceTypes + */ + public toString(): string { + const resourceTypes: string[] = []; + if (this.service) { + resourceTypes.push(AccountSASResourceType.Service); + } + if (this.container) { + resourceTypes.push(AccountSASResourceType.Container); + } + if (this.object) { + resourceTypes.push(AccountSASResourceType.Object); + } + return resourceTypes.join(""); + } +} diff --git a/src/table/authentication/AccountSASServices.ts b/src/table/authentication/AccountSASServices.ts new file mode 100644 index 000000000..5723ccaac --- /dev/null +++ b/src/table/authentication/AccountSASServices.ts @@ -0,0 +1,121 @@ +export enum AccountSASService { + Blob = "b", + File = "f", + Queue = "q", + Table = "t" +} + +/** + * ONLY AVAILABLE IN NODE.JS RUNTIME. + * + * This is a helper class to construct a string representing the services accessible by an AccountSAS. Setting a value + * to true means that any SAS which uses these permissions will grant access to that service. Once all the + * values are set, this should be serialized with toString and set as the services field on an + * {@link AccountSASSignatureValues} object. It is possible to construct the services string without this class, but + * the order of the services is particular and this class guarantees correctness. + * + * @export + * @class AccountSASServices + */ +export default class AccountSASServices { + /** + * Creates an {@link AccountSASServices} from the specified services string. This method will throw an + * Error if it encounters a character that does not correspond to a valid service. + * + * @static + * @param {string} services + * @returns {AccountSASServices} + * @memberof AccountSASServices + */ + public static parse(services: string): AccountSASServices { + const accountSASServices = new AccountSASServices(); + + for (const c of services) { + switch (c) { + case AccountSASService.Blob: + if (accountSASServices.blob) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASServices.blob = true; + break; + case AccountSASService.File: + if (accountSASServices.file) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASServices.file = true; + break; + case AccountSASService.Queue: + if (accountSASServices.queue) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASServices.queue = true; + break; + case AccountSASService.Table: + if (accountSASServices.table) { + throw new RangeError(`Duplicated permission character: ${c}`); + } + accountSASServices.table = true; + break; + default: + throw new RangeError(`Invalid service character: ${c}`); + } + } + + return accountSASServices; + } + + /** + * Permission to access blob resources granted. + * + * @type {boolean} + * @memberof AccountSASServices + */ + public blob: boolean = false; + + /** + * Permission to access file resources granted. + * + * @type {boolean} + * @memberof AccountSASServices + */ + public file: boolean = false; + + /** + * Permission to access queue resources granted. + * + * @type {boolean} + * @memberof AccountSASServices + */ + public queue: boolean = false; + + /** + * Permission to access table resources granted. + * + * @type {boolean} + * @memberof AccountSASServices + */ + public table: boolean = false; + + /** + * Converts the given services to a string. + * + * @returns {string} + * @memberof AccountSASServices + */ + public toString(): string { + const services: string[] = []; + if (this.blob) { + services.push(AccountSASService.Blob); + } + if (this.table) { + services.push(AccountSASService.Table); + } + if (this.queue) { + services.push(AccountSASService.Queue); + } + if (this.file) { + services.push(AccountSASService.File); + } + return services.join(""); + } +} diff --git a/src/table/authentication/IAccountSASSignatureValues.ts b/src/table/authentication/IAccountSASSignatureValues.ts new file mode 100644 index 000000000..7b0e6e48f --- /dev/null +++ b/src/table/authentication/IAccountSASSignatureValues.ts @@ -0,0 +1,167 @@ +import { IIPRange } from "@azure/storage-blob"; + +import { + computeHMACSHA256, + truncatedISO8061Date +} from "../../common/utils/utils"; +import AccountSASPermissions from "./AccountSASPermissions"; +import AccountSASResourceTypes from "./AccountSASResourceTypes"; +import AccountSASServices from "./AccountSASServices"; +import { ipRangeToString } from "./IIPRange"; + +/** + * Protocols for generated SAS. + * + * @export + * @enum {number} + */ +export enum SASProtocol { + /** + * Protocol that allows HTTPS only + */ + HTTPS = "https", + + /** + * Protocol that allows both HTTPS and HTTP + */ + HTTPSandHTTP = "https,http" +} + +/** + * IAccountSASSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage account. + * + * @see https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1 + * for more conceptual information on SAS + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + * for descriptions of the parameters, including which are required + * + * @export + * @class IAccountSASSignatureValues + */ +export interface IAccountSASSignatureValues { + /** + * If not provided, this defaults to the service version targeted by this version of the library. + * + * @type {string} + * @memberof IAccountSASSignatureValues + */ + version: string; + + /** + * Optional. SAS protocols allowed. + * + * @type {SASProtocol | string} + * @memberof IAccountSASSignatureValues + */ + protocol?: SASProtocol | string; + + /** + * Optional. When the SAS will take effect. + * + * @type {Date | string} + * @memberof IAccountSASSignatureValues + */ + startTime?: Date | string; + + /** + * The time after which the SAS will no longer work. + * + * @type {Date | string} + * @memberof IAccountSASSignatureValues + */ + expiryTime: Date | string; + + /** + * Specifies which operations the SAS user may perform. Please refer to {@link AccountSASPermissions} for help + * constructing the permissions string. + * + * @type {AccountSASPermissions | string} + * @memberof IAccountSASSignatureValues + */ + permissions: AccountSASPermissions | string; + + /** + * Optional. IP range allowed. + * + * @type {IIPRange | string} + * @memberof IAccountSASSignatureValues + */ + ipRange?: IIPRange | string; + + /** + * The values that indicate the services accessible with this SAS. Please refer to {@link AccountSASServices} to + * construct this value. + * + * @type {AccountSASServices | string} + * @memberof IAccountSASSignatureValues + */ + services: AccountSASServices | string; + + /** + * The values that indicate the resource types accessible with this SAS. Please refer + * to {@link AccountSASResourceTypes} to construct this value. + * + * @type {AccountSASResourceType | string} + * @memberof IAccountSASSignatureValues + */ + resourceTypes: AccountSASResourceTypes | string; +} + +/** + * Generates signature string from account SAS parameters. + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-an-account-sas + * + * @param {SharedKeyCredential} sharedKeyCredential + * @param {string} accountName + * @param {Buffer} sharedKey + * @returns {[string, string]} signature and stringToSign + * @memberof IAccountSASSignatureValues + */ +export function generateAccountSASSignature( + accountSASSignatureValues: IAccountSASSignatureValues, + accountName: string, + sharedKey: Buffer +): [string, string] { + const parsedPermissions = accountSASSignatureValues.permissions.toString(); + const parsedServices = accountSASSignatureValues.services.toString(); + const parsedResourceTypes = accountSASSignatureValues.resourceTypes.toString(); + const parsedStartTime = + accountSASSignatureValues.startTime === undefined + ? "" + : typeof accountSASSignatureValues.startTime === "string" + ? accountSASSignatureValues.startTime + : truncatedISO8061Date(accountSASSignatureValues.startTime, false); + const parsedExpiryTime = + typeof accountSASSignatureValues.expiryTime === "string" + ? accountSASSignatureValues.expiryTime + : truncatedISO8061Date(accountSASSignatureValues.expiryTime, false); + const parsedIPRange = + accountSASSignatureValues.ipRange === undefined + ? "" + : typeof accountSASSignatureValues.ipRange === "string" + ? accountSASSignatureValues.ipRange + : ipRangeToString(accountSASSignatureValues.ipRange); + const parsedProtocol = + accountSASSignatureValues.protocol === undefined + ? "" + : accountSASSignatureValues.protocol; + const version = accountSASSignatureValues.version; + + const stringToSign = [ + accountName, + parsedPermissions, + parsedServices, + parsedResourceTypes, + parsedStartTime, + parsedExpiryTime, + parsedIPRange, + parsedProtocol, + version, + "" // Account SAS requires an additional newline character + ].join("\n"); + + const signature: string = computeHMACSHA256(stringToSign, sharedKey); + return [signature, stringToSign]; +} diff --git a/src/table/authentication/IAuthenticationContext.ts b/src/table/authentication/IAuthenticationContext.ts new file mode 100644 index 000000000..b6517487f --- /dev/null +++ b/src/table/authentication/IAuthenticationContext.ts @@ -0,0 +1,3 @@ +export default interface IAuthenticationContext { + account?: string; +} diff --git a/src/table/authentication/IAuthenticator.ts b/src/table/authentication/IAuthenticator.ts new file mode 100644 index 000000000..79d973cb0 --- /dev/null +++ b/src/table/authentication/IAuthenticator.ts @@ -0,0 +1,6 @@ +import Context from "../generated/Context"; +import IRequest from "../generated/IRequest"; + +export default interface IAuthenticator { + validate(req: IRequest, content: Context): Promise; +} diff --git a/src/table/authentication/IIPRange.ts b/src/table/authentication/IIPRange.ts new file mode 100644 index 000000000..aa1503787 --- /dev/null +++ b/src/table/authentication/IIPRange.ts @@ -0,0 +1,37 @@ +/** + * Allowed IP range for a SAS. + * + * @export + * @interface IIPRange + */ +export interface IIPRange { + /** + * Starting IP address in the IP range. + * If end IP doesn't provide, start IP will the only IP allowed. + * + * @type {string} + * @memberof IPRange + */ + start: string; + /** + * Optional. IP address that ends the IP range. + * If not provided, start IP will the only IP allowed. + * + * @type {string} + * @memberof IPRange + */ + end?: string; +} + +/** + * Generate IPRange format string. For example: + * + * "8.8.8.8" or "1.1.1.1-255.255.255.255" + * + * @export + * @param {IIPRange} ipRange + * @returns {string} + */ +export function ipRangeToString(ipRange: IIPRange): string { + return ipRange.end ? `${ipRange.start}-${ipRange.end}` : ipRange.start; +} diff --git a/src/table/authentication/ITableSASSignatureValues.ts b/src/table/authentication/ITableSASSignatureValues.ts new file mode 100644 index 000000000..8bea1e49b --- /dev/null +++ b/src/table/authentication/ITableSASSignatureValues.ts @@ -0,0 +1,249 @@ +import { + computeHMACSHA256, + truncatedISO8061Date +} from "../../common/utils/utils"; +import { SASProtocol } from "./IAccountSASSignatureValues"; +import { IIPRange, ipRangeToString } from "./IIPRange"; + +/** + * ITableSASSignatureValues is used to help generating Table service SAS tokens for containers or tables. + * + * @export + * @class ITableSASSignatureValues + */ +export interface ITableSASSignatureValues { + /** + * The version of the service this SAS will target. If not specified, it will default to the version targeted by the + * library. + * + * @type {string} + * @memberof ITableSASSignatureValues + */ + version: string; + + /** + * Optional. SAS protocols, HTTPS only or HTTPSandHTTP + * + * @type {SASProtocol | string} + * @memberof ITableSASSignatureValues + */ + protocol?: SASProtocol | string; + + /** + * Optional. When the SAS will take effect. + * + * @type {Date | string} + * @memberof ITableSASSignatureValues + */ + startTime?: Date | string; + + /** + * Optional only when identifier is provided. The time after which the SAS will no longer work. + * + * @type {Date | string} + * @memberof ITableSASSignatureValues + */ + expiryTime?: Date | string; + + /** + * Optional only when identifier is provided. + * Please refer to either {@link ContainerSASPermissions} or {@link TableSASPermissions} depending on the resource + * being accessed for help constructing the permissions string. + * + * @type {string} + * @memberof ITableSASSignatureValues + */ + permissions?: string; + + /** + * Optional. IP ranges allowed in this SAS. + * + * @type {IIPRange | string} + * @memberof ITableSASSignatureValues + */ + ipRange?: IIPRange | string; + + /** + * The name of the table the SAS user may access. + * + * @type {string} + * @memberof ITableSASSignatureValues + */ + tableName: string; + + /** + * Optional. The name of the access policy on the container this SAS references if any. + * + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/establishing-a-stored-access-policy + * + * @type {string} + * @memberof ITableSASSignatureValues + */ + identifier?: string; + + startingPartitionKey?: string; + startingRowKey?: string; + endingPartitionKey?: string; + endingRowKey?: string; +} + +/** + * Creates an instance of SASQueryParameters. + * + * Only accepts required settings needed to create a SAS. For optional settings please + * set corresponding properties directly, such as permissions, startTime and identifier. + * + * WARNING: When identifier is not provided, permissions and expiryTime are required. + * You MUST assign value to identifier or expiryTime & permissions manually if you initial with + * this constructor. + * + * @export + * @param {ITableSASSignatureValues} tableSASSignatureValues + * @param {TableSASResourceType} resource + * @param {string} accountName + * @param {Buffer} sharedKey + * @returns {[string, string]} signature and stringToSign + */ +export function generateTableSASSignature( + tableSASSignatureValues: ITableSASSignatureValues, + accountName: string, + sharedKey: Buffer +): [string, string] { + if (tableSASSignatureValues.version >= "2018-11-09") { + return generateTableSASSignature20181109( + tableSASSignatureValues, + accountName, + sharedKey + ); + } else { + return generateTableSASSignature20150405( + tableSASSignatureValues, + accountName, + sharedKey + ); + } +} + +function generateTableSASSignature20181109( + tableSASSignatureValues: ITableSASSignatureValues, + accountName: string, + sharedKey: Buffer +): [string, string] { + if ( + !tableSASSignatureValues.identifier && + (!tableSASSignatureValues.permissions && + !tableSASSignatureValues.expiryTime) + ) { + throw new RangeError( + // tslint:disable-next-line:max-line-length + "generateTableSASSignature(): Must provide 'permissions' and 'expiryTime' for Table SAS generation when 'identifier' is not provided." + ); + } + + const version = tableSASSignatureValues.version; + const verifiedPermissions = tableSASSignatureValues.permissions; + + // Signature is generated on the un-url-encoded values. + // TODO: Check whether validating the snapshot is necessary. + const stringToSign = [ + verifiedPermissions ? verifiedPermissions : "", + tableSASSignatureValues.startTime === undefined + ? "" + : typeof tableSASSignatureValues.startTime === "string" + ? tableSASSignatureValues.startTime + : truncatedISO8061Date(tableSASSignatureValues.startTime, false), + tableSASSignatureValues.expiryTime === undefined + ? "" + : typeof tableSASSignatureValues.expiryTime === "string" + ? tableSASSignatureValues.expiryTime + : truncatedISO8061Date(tableSASSignatureValues.expiryTime, false), + getCanonicalName(accountName, tableSASSignatureValues.tableName), + tableSASSignatureValues.identifier, // TODO: ? tableSASSignatureValues.identifier : "", + tableSASSignatureValues.ipRange + ? typeof tableSASSignatureValues.ipRange === "string" + ? tableSASSignatureValues.ipRange + : ipRangeToString(tableSASSignatureValues.ipRange) + : "", + tableSASSignatureValues.protocol ? tableSASSignatureValues.protocol : "", + version, + tableSASSignatureValues.startingPartitionKey + ? tableSASSignatureValues.startingPartitionKey + : "", + tableSASSignatureValues.startingRowKey + ? tableSASSignatureValues.startingRowKey + : "", + tableSASSignatureValues.endingPartitionKey + ? tableSASSignatureValues.endingPartitionKey + : "", + tableSASSignatureValues.endingRowKey + ? tableSASSignatureValues.endingRowKey + : "" + ].join("\n"); + + const signature = computeHMACSHA256(stringToSign, sharedKey); + return [signature, stringToSign]; +} + +function generateTableSASSignature20150405( + tableSASSignatureValues: ITableSASSignatureValues, + + accountName: string, + sharedKey: Buffer +): [string, string] { + if ( + !tableSASSignatureValues.identifier && + (!tableSASSignatureValues.permissions && + !tableSASSignatureValues.expiryTime) + ) { + throw new RangeError( + // tslint:disable-next-line:max-line-length + "generateTableSASSignature(): Must provide 'permissions' and 'expiryTime' for Table SAS generation when 'identifier' is not provided." + ); + } + + const version = tableSASSignatureValues.version; + const verifiedPermissions = tableSASSignatureValues.permissions; + + // Signature is generated on the un-url-encoded values. + const stringToSign = [ + verifiedPermissions ? verifiedPermissions : "", + tableSASSignatureValues.startTime === undefined + ? "" + : typeof tableSASSignatureValues.startTime === "string" + ? tableSASSignatureValues.startTime + : truncatedISO8061Date(tableSASSignatureValues.startTime, false), + tableSASSignatureValues.expiryTime === undefined + ? "" + : typeof tableSASSignatureValues.expiryTime === "string" + ? tableSASSignatureValues.expiryTime + : truncatedISO8061Date(tableSASSignatureValues.expiryTime, false), + getCanonicalName(accountName, tableSASSignatureValues.tableName), + tableSASSignatureValues.identifier, // TODO: ? tableSASSignatureValues.identifier : "", + tableSASSignatureValues.ipRange + ? typeof tableSASSignatureValues.ipRange === "string" + ? tableSASSignatureValues.ipRange + : ipRangeToString(tableSASSignatureValues.ipRange) + : "", + tableSASSignatureValues.protocol ? tableSASSignatureValues.protocol : "", + version, + tableSASSignatureValues.startingPartitionKey + ? tableSASSignatureValues.startingPartitionKey + : "", + tableSASSignatureValues.startingRowKey + ? tableSASSignatureValues.startingRowKey + : "", + tableSASSignatureValues.endingPartitionKey + ? tableSASSignatureValues.endingPartitionKey + : "", + tableSASSignatureValues.endingRowKey + ? tableSASSignatureValues.endingRowKey + : "" + ].join("\n"); + + const signature = computeHMACSHA256(stringToSign, sharedKey); + return [signature, stringToSign]; +} + +function getCanonicalName(accountName: string, tableName: string): string { + return `/table/${accountName}/${tableName}`; +} diff --git a/src/table/authentication/OperationAccountSASPermission.ts b/src/table/authentication/OperationAccountSASPermission.ts new file mode 100644 index 000000000..266d5308f --- /dev/null +++ b/src/table/authentication/OperationAccountSASPermission.ts @@ -0,0 +1,205 @@ +import { + AccountSASPermissions, + AccountSASResourceTypes, + AccountSASServices +} from "@azure/storage-blob"; + +import Operation from "../generated/artifacts/operation"; +import { AccountSASPermission } from "./AccountSASPermissions"; +import { AccountSASResourceType } from "./AccountSASResourceTypes"; +import { AccountSASService } from "./AccountSASServices"; + +export class OperationAccountSASPermission { + constructor( + public readonly service: string, + public readonly resourceType: string, + public readonly permission: string + ) {} + + public validate( + services: AccountSASServices | string, + resourceTypes: AccountSASResourceTypes | string, + permissions: AccountSASPermissions | string + ): boolean { + return ( + this.validateServices(services) && + this.validateResourceTypes(resourceTypes) && + this.validatePermissions(permissions) + ); + } + + public validateServices(services: AccountSASServices | string): boolean { + return services.toString().includes(this.service); + } + + public validateResourceTypes( + resourceTypes: AccountSASResourceTypes | string + ): boolean { + for (const p of this.resourceType) { + if (resourceTypes.toString().includes(p)) { + return true; + } + } + return false; + } + + public validatePermissions( + permissions: AccountSASPermissions | string + ): boolean { + for (const p of this.permission) { + if (permissions.toString().includes(p)) { + return true; + } + } + return false; + } +} + +// The permissions are in the table order +// See https://docs.microsoft.com/en-us/rest/api/storageservices/create-account-sas#table-service +// TODO: Check all required operations +const OPERATION_ACCOUNT_SAS_PERMISSIONS = new Map< + Operation, + OperationAccountSASPermission +>(); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Service_GetProperties, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Service, + AccountSASPermission.Read + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Service_SetProperties, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Service, + AccountSASPermission.Write + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Service_GetStatistics, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Service, + AccountSASPermission.Read + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_Query, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Container, + AccountSASPermission.List + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_Create, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Container, + AccountSASPermission.Create + AccountSASPermission.Write + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_SetAccessPolicy, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Container, + "" // NOT ALLOWED + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_GetAccessPolicy, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Container, + "" // NOT ALLOWED + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_Delete, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Container, + AccountSASPermission.Delete + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_QueryEntities, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Container, + AccountSASPermission.Read + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_QueryEntitiesWithPartitionAndRowKey, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Object, + AccountSASPermission.Read + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_InsertEntity, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Object, + AccountSASPermission.Add + ) +); + +// TODO do we need to specify InsertOrMergeEntity? +// TODO do we need to specify InsertOrUpdateEntity +// or are they two separate operations with respective permissions + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_UpdateEntity, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Object, + AccountSASPermission.Update + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_MergeEntity, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Object, + AccountSASPermission.Update + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_MergeEntityWithMerge, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Object, + AccountSASPermission.Update + ) +); + +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_DeleteEntity, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Object, + AccountSASPermission.Delete + ) +); + +export default OPERATION_ACCOUNT_SAS_PERMISSIONS; diff --git a/src/table/authentication/OperationTableSASPermission.ts b/src/table/authentication/OperationTableSASPermission.ts new file mode 100644 index 000000000..5d4df7b55 --- /dev/null +++ b/src/table/authentication/OperationTableSASPermission.ts @@ -0,0 +1,131 @@ +import Operation from "../generated/artifacts/operation"; +import { TableSASPermission } from "./TableSASPermissions"; + +export class OperationTableSASPermission { + constructor(public readonly permission: string = "") {} + + public validate(permissions: string): boolean { + return this.validatePermissions(permissions); + } + + public validatePermissions(permissions: string): boolean { + for (const p of this.permission) { + if (permissions.toString().includes(p)) { + return true; + } + } + return false; + } +} + +// See https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas +// Table Service SAS Permissions for table level +export const OPERATION_TABLE_SAS_TABLE_PERMISSIONS = new Map< + Operation, + OperationTableSASPermission +>(); + +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Service_SetProperties, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Service_GetProperties, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Service_GetStatistics, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_Query, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_Create, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_Delete, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_QueryEntities, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_QueryEntitiesWithPartitionAndRowKey, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_UpdateEntity, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_MergeEntity, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_DeleteEntity, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_MergeEntityWithMerge, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_InsertEntity, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_GetAccessPolicy, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_SetAccessPolicy, + new OperationTableSASPermission() +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_InsertEntity, + new OperationTableSASPermission(TableSASPermission.Add) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_Query, + new OperationTableSASPermission(TableSASPermission.Query) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_QueryEntities, + new OperationTableSASPermission(TableSASPermission.Query) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_QueryEntitiesWithPartitionAndRowKey, + new OperationTableSASPermission(TableSASPermission.Query) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Service_GetProperties, + new OperationTableSASPermission(TableSASPermission.Query) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Service_GetStatistics, + new OperationTableSASPermission(TableSASPermission.Query) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_Delete, + new OperationTableSASPermission(TableSASPermission.Delete) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_DeleteEntity, + new OperationTableSASPermission(TableSASPermission.Delete) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_UpdateEntity, + new OperationTableSASPermission(TableSASPermission.Update) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_MergeEntity, + new OperationTableSASPermission(TableSASPermission.Update) +); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_MergeEntityWithMerge, + new OperationTableSASPermission(TableSASPermission.Update) +); diff --git a/src/table/authentication/TableSASAuthenticator.ts b/src/table/authentication/TableSASAuthenticator.ts new file mode 100644 index 000000000..574c56ad8 --- /dev/null +++ b/src/table/authentication/TableSASAuthenticator.ts @@ -0,0 +1,409 @@ +import IAccountDataStore from "../../common/IAccountDataStore"; +import ILogger from "../../common/ILogger"; +import TableStorageContext from "../context/TableStorageContext"; +import StorageErrorFactory from "../errors/StorageErrorFactory"; +import { AccessPolicy } from "../generated/artifacts/models"; +import Operation from "../generated/artifacts/operation"; +import Context from "../generated/Context"; +import IRequest from "../generated/IRequest"; +import ITableMetadataStore from "../persistence/ITableMetadataStore"; +import IAuthenticator from "./IAuthenticator"; +import { + generateTableSASSignature, + ITableSASSignatureValues +} from "./ITableSASSignatureValues"; +import { OPERATION_TABLE_SAS_TABLE_PERMISSIONS } from "./OperationTableSASPermission"; + +export default class TableSASAuthenticator implements IAuthenticator { + public constructor( + private readonly accountDataStore: IAccountDataStore, + private readonly tableMetadataStore: ITableMetadataStore, + private readonly logger: ILogger + ) {} + + public async validate( + req: IRequest, + context: Context + ): Promise { + this.logger.info( + `TableSASAuthenticator:validate() Start validation against table service Shared Access Signature pattern.`, + context.contextID + ); + + this.logger.debug( + "TableSASAuthenticator:validate() Getting account properties...", + context.contextID + ); + + const tableContext = new TableStorageContext(context); + const account = tableContext.account; + if (account === undefined) { + throw RangeError( + `TableSASAuthenticator:validate() account is undefined in context.` + ); + } + + const tableName = tableContext.tableName; + + if (tableName === undefined) { + this.logger.error( + `TableSASAuthenticator:validate() table name is undefined in context.`, + context.contextID + ); + return undefined; + } + + this.logger.debug( + // tslint:disable-next-line:max-line-length + `TableSASAuthenticator:validate() Retrieved account name from context: ${account}, table: ${tableName}`, + context.contextID + ); + + // TODO: Make following async + const accountProperties = this.accountDataStore.getAccount(account); + if (accountProperties === undefined) { + throw StorageErrorFactory.getInvalidOperation( + context.contextID!, + "Invalid storage account." + ); + } + this.logger.debug( + "TableSASAuthenticator:validate() Got account properties successfully.", + context.contextID + ); + + // Extract table service SAS authentication required parameters + const signature = this.decodeIfExist(req.getQuery("sig")); + this.logger.debug( + `TableSASAuthenticator:validate() Retrieved signature from URL parameter sig: ${signature}`, + context.contextID + ); + if (signature === undefined) { + this.logger.debug( + `TableSASAuthenticator:validate() No signature found in request. Skip table service SAS validation.`, + context.contextID + ); + return undefined; + } + + const values = this.getTableSASSignatureValuesFromRequest( + req, + tableName, + context + ); + if (values === undefined) { + this.logger.info( + // tslint:disable-next-line:max-line-length + `TableSASAuthenticator:validate() Failed to get valid table service SAS values from request. Skip table service SAS validation.`, + context.contextID + ); + return undefined; + } + + this.logger.debug( + `TableSASAuthenticator:validate() Successfully got valid table service SAS values from request. ${JSON.stringify( + values + )}`, + context.contextID + ); + + this.logger.info( + `TableSASAuthenticator:validate() Validate signature based account key1.`, + context.contextID + ); + const [sig1, stringToSign1] = generateTableSASSignature( + values, + account, + accountProperties.key1 + ); + this.logger.debug( + `TableSASAuthenticator:validate() String to sign is: ${JSON.stringify( + stringToSign1 + )}`, + context.contextID! + ); + this.logger.debug( + `TableSASAuthenticator:validate() Calculated signature is: ${sig1}`, + context.contextID! + ); + + const sig1Pass = sig1 === signature; + this.logger.info( + `TableSASAuthenticator:validate() Signature based on key1 validation ${ + sig1Pass ? "passed" : "failed" + }.`, + context.contextID + ); + + if (accountProperties.key2 !== undefined) { + this.logger.info( + `TableSASAuthenticator:validate() Account key2 is not empty, validate signature based account key2.`, + context.contextID + ); + const [sig2, stringToSign2] = generateTableSASSignature( + values, + account, + accountProperties.key2 + ); + this.logger.debug( + `TableSASAuthenticator:validate() String to sign is: ${JSON.stringify( + stringToSign2 + )}`, + context.contextID! + ); + this.logger.debug( + `TableSASAuthenticator:validate() Calculated signature is: ${sig2}`, + context.contextID! + ); + + const sig2Pass = sig2 !== signature; + this.logger.info( + `TableSASAuthenticator:validate() Signature based on key2 validation ${ + sig2Pass ? "passed" : "failed" + }.`, + context.contextID + ); + + if (!sig2Pass && !sig1Pass) { + this.logger.info( + `TableSASAuthenticator:validate() Validate signature based account key1 and key2 failed.`, + context.contextID + ); + return false; + } + } else { + if (!sig1Pass) { + return false; + } + } + + // When signature validation passes, we enforce table service SAS validation + // Any validation errors will stop this request immediately + + // TODO: Validate permissions from ACL identifier by extract permissions, start time and expiry time from ACL + if (values.identifier !== undefined) { + const accessPolicy: + | AccessPolicy + | undefined = await this.getTableAccessPolicyByIdentifier( + tableName, + values.identifier, + context + ); + if (accessPolicy === undefined) { + this.logger.warn( + `TableSASAuthenticator:validate() Cannot get access policy defined for table ${tableName} with id ${values.identifier}.`, + context.contextID + ); + throw StorageErrorFactory.getAuthorizationFailure(context.contextID!); + } + + values.startTime = accessPolicy.start; + values.expiryTime = accessPolicy.expiry; + values.permissions = accessPolicy.permission; + } + + this.logger.info( + `TableSASAuthenticator:validate() Validate start and expiry time.`, + context.contextID + ); + if (!this.validateTime(values.expiryTime, values.startTime)) { + this.logger.info( + `TableSASAuthenticator:validate() Validate start and expiry failed.`, + context.contextID + ); + throw StorageErrorFactory.getAuthorizationFailure(context.contextID!); + } + + this.logger.info( + `TableSASAuthenticator:validate() Validate IP range.`, + context.contextID + ); + if (!this.validateIPRange()) { + this.logger.info( + `TableSASAuthenticator:validate() Validate IP range failed.`, + context.contextID + ); + throw StorageErrorFactory.getAuthorizationSourceIPMismatch( + context.contextID! + ); + } + + this.logger.info( + `TableSASAuthenticator:validate() Validate request protocol.`, + context.contextID + ); + if (!this.validateProtocol(values.protocol, req.getProtocol())) { + this.logger.info( + `TableSASAuthenticator:validate() Validate protocol failed.`, + context.contextID + ); + throw StorageErrorFactory.getAuthorizationProtocolMismatch( + context.contextID! + ); + } + + const operation = context.operation; + if (operation === undefined) { + throw new Error( + // tslint:disable-next-line:max-line-length + `TableSASAuthenticator:validate() Operation shouldn't be undefined. Please make sure DispatchMiddleware is hooked before authentication related middleware.` + ); + } + + const tableSASPermission = OPERATION_TABLE_SAS_TABLE_PERMISSIONS.get( + operation + ); + + this.logger.debug( + `TableSASAuthenticator:validate() Got permission requirements for operation ${ + Operation[operation] + } - ${JSON.stringify(tableSASPermission)}`, + context.contextID + ); + if (tableSASPermission === undefined) { + throw new Error( + // tslint:disable-next-line:max-line-length + `TableSASAuthenticator:validate() ${"OPERATION_TABLE_SAS_TABLE_PERMISSIONS"} doesn't have configuration for operation ${ + Operation[operation] + }'s table service SAS permission.` + ); + } + + if (!tableSASPermission.validatePermissions(values.permissions!)) { + throw StorageErrorFactory.getAuthorizationPermissionMismatch( + context.contextID! + ); + } + + this.logger.info( + `TableSASAuthenticator:validate() Table service SAS validation successfully.`, + context.contextID + ); + + // TODO: Handle enforced response headers defined in table service SAS + + return true; + } + + private getTableSASSignatureValuesFromRequest( + req: IRequest, + tableName: string, + context?: Context + ): ITableSASSignatureValues | undefined { + const version = this.decodeIfExist(req.getQuery("sv")); + const protocol = this.decodeIfExist(req.getQuery("spr")); + const startTime = this.decodeIfExist(req.getQuery("st")); + const expiryTime = this.decodeIfExist(req.getQuery("se")); + const permissions = this.decodeIfExist(req.getQuery("sp")); + const ipRange = this.decodeIfExist(req.getQuery("sip")); + const identifier = this.decodeIfExist(req.getQuery("si")); + const startingPartitionKey = this.decodeIfExist(req.getQuery("spk")); + const startingRowKey = this.decodeIfExist(req.getQuery("srk")); + const endingPartitionKey = this.decodeIfExist(req.getQuery("epk")); + const endingRowKey = this.decodeIfExist(req.getQuery("erk")); + + if (!identifier && (!permissions || !expiryTime)) { + this.logger.warn( + // tslint:disable-next-line:max-line-length + `TableSASAuthenticator:generateTableSASSignature(): Must provide 'permissions' and 'expiryTime' for Table SAS generation when 'identifier' is not provided.`, + context ? context.contextID : undefined + ); + return undefined; + } + + if (version === undefined) { + this.logger.warn( + // tslint:disable-next-line:max-line-length + `TableSASAuthenticator:generateTableSASSignature(): Must provide 'version'.`, + context ? context.contextID : undefined + ); + return undefined; + } + + const tableSASValues: ITableSASSignatureValues = { + version, + protocol, + startTime, + expiryTime, + permissions, + ipRange, + tableName, + identifier, + startingPartitionKey, + startingRowKey, + endingPartitionKey, + endingRowKey + }; + + return tableSASValues; + } + + private validateTime(expiry?: Date | string, start?: Date | string): boolean { + if (expiry === undefined && start === undefined) { + return true; + } + + const now = new Date(); + + if (expiry !== undefined) { + const expiryTime = new Date(expiry); + if (now > expiryTime) { + return false; + } + } + + if (start !== undefined) { + const startTime = new Date(start); + if (now < startTime) { + return false; + } + } + + return true; + } + + private validateIPRange(): boolean { + // TODO: Emulator doesn't validate IP Address + return true; + } + + private validateProtocol( + sasProtocol: string = "https,http", + requestProtocol: string + ): boolean { + if (sasProtocol.includes(",")) { + return true; + } else { + return sasProtocol.toLowerCase() === requestProtocol; + } + } + + private decodeIfExist(value?: string): string | undefined { + return value === undefined ? value : decodeURIComponent(value); + } + + private async getTableAccessPolicyByIdentifier( + table: string, + id: string, + context: Context + ): Promise { + try { + const containerModel = await this.tableMetadataStore.getTableAccessPolicy( + context, + table, + {} + ); + if (containerModel === undefined) { + return undefined; + } + + for (const acl of containerModel) { + if (acl.id === id) { + return acl.accessPolicy; + } + } + } catch (err) { + return undefined; + } + } +} diff --git a/src/table/authentication/TableSASPermissions.ts b/src/table/authentication/TableSASPermissions.ts new file mode 100644 index 000000000..e3b09642a --- /dev/null +++ b/src/table/authentication/TableSASPermissions.ts @@ -0,0 +1,6 @@ +export enum TableSASPermission { + Query = "r", + Add = "a", + Update = "c", + Delete = "d" +} diff --git a/src/table/authentication/TableSharedKeyAuthenticator.ts b/src/table/authentication/TableSharedKeyAuthenticator.ts new file mode 100644 index 000000000..5c617c813 --- /dev/null +++ b/src/table/authentication/TableSharedKeyAuthenticator.ts @@ -0,0 +1,190 @@ +import IAccountDataStore from "../../common/IAccountDataStore"; +import ILogger from "../../common/ILogger"; +import { computeHMACSHA256, getURLQueries } from "../../common/utils/utils"; +import TableStorageContext from "../context/TableStorageContext"; +import StorageErrorFactory from "../errors/StorageErrorFactory"; +import Context from "../generated/Context"; +import IRequest from "../generated/IRequest"; +import { HeaderConstants } from "../utils/constants"; +import IAuthenticator from "./IAuthenticator"; + +export default class TableSharedKeyAuthenticator implements IAuthenticator { + public constructor( + private readonly dataStore: IAccountDataStore, + private readonly logger: ILogger + ) {} + + public async validate( + req: IRequest, + context: Context + ): Promise { + const tableContext = new TableStorageContext(context); + const account = tableContext.account!; + + this.logger.info( + `TableSharedKeyAuthenticator:validate() Start validation against account shared key authentication.`, + tableContext.contextID + ); + + const authHeaderValue = req.getHeader(HeaderConstants.AUTHORIZATION); + if (authHeaderValue === undefined) { + this.logger.info( + // tslint:disable-next-line:max-line-length + `TableSharedKeyAuthenticator:validate() Request doesn't include valid authentication header. Skip shared key authentication.`, + tableContext.contextID + ); + return undefined; + } + + // TODO: Make following async + const accountProperties = this.dataStore.getAccount(account); + if (accountProperties === undefined) { + this.logger.error( + `TableSharedKeyAuthenticator:validate() Invalid storage account ${account}.`, + tableContext.contextID + ); + throw StorageErrorFactory.getInvalidOperation( + tableContext.contextID!, + "Invalid storage account." + ); + } + + const stringToSign: string = + [ + req.getMethod().toUpperCase(), + this.getHeaderValueToSign(req, HeaderConstants.CONTENT_MD5), + this.getHeaderValueToSign(req, HeaderConstants.CONTENT_TYPE), + this.getHeaderValueToSign(req, HeaderConstants.DATE) || + this.getHeaderValueToSign(req, HeaderConstants.X_MS_DATE) + ].join("\n") + + "\n" + + this.getCanonicalizedResourceString( + req, + account, + tableContext.authenticationPath + ); + + this.logger.info( + `TableSharedKeyAuthenticator:validate() [STRING TO SIGN]:${JSON.stringify( + stringToSign + )}`, + tableContext.contextID + ); + + const signature1 = computeHMACSHA256(stringToSign, accountProperties.key1); + const authValue1 = `SharedKey ${account}:${signature1}`; + this.logger.info( + `TableSharedKeyAuthenticator:validate() Calculated authentication header based on key1: ${authValue1}`, + tableContext.contextID + ); + if (authHeaderValue === authValue1) { + this.logger.info( + `TableSharedKeyAuthenticator:validate() Signature 1 matched.`, + tableContext.contextID + ); + return true; + } + + if (accountProperties.key2) { + const signature2 = computeHMACSHA256( + stringToSign, + accountProperties.key2 + ); + const authValue2 = `SharedKey ${account}:${signature2}`; + this.logger.info( + `TableSharedKeyAuthenticator:validate() Calculated authentication header based on key2: ${authValue2}`, + tableContext.contextID + ); + if (authHeaderValue === authValue2) { + this.logger.info( + `TableSharedKeyAuthenticator:validate() Signature 2 matched.`, + tableContext.contextID + ); + return true; + } + } + + // this.logger.info(`[URL]:${req.getUrl()}`); + // this.logger.info(`[HEADERS]:${req.getHeaders().toString()}`); + // this.logger.info(`[KEY]: ${request.headers.get(HeaderConstants.AUTHORIZATION)}`); + + this.logger.info( + `TableSharedKeyAuthenticator:validate() Validation failed.`, + tableContext.contextID + ); + return false; + } + + /** + * Retrieve header value according to shared key sign rules. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + * + * @private + * @param {WebResource} request + * @param {string} headerName + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ + private getHeaderValueToSign(request: IRequest, headerName: string): string { + const value = request.getHeader(headerName); + + if (!value) { + return ""; + } + + // When using version 2015-02-21 or later, if Content-Length is zero, then + // set the Content-Length part of the StringToSign to an empty string. + // https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + if (headerName === HeaderConstants.CONTENT_LENGTH && value === "0") { + return ""; + } + + return value; + } + + /** + * Retrieves canonicalized resource string. + * + * @private + * @param {IRequest} request + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ + private getCanonicalizedResourceString( + request: IRequest, + account: string, + authenticationPath?: string + ): string { + let path = request.getPath() || "/"; + + // For secondary account, we use account name (without "-secondary") for the path + if (authenticationPath !== undefined) { + path = authenticationPath; + } + + let canonicalizedResourceString: string = ""; + canonicalizedResourceString += `/${account}${path}`; + + const queries = getURLQueries(request.getUrl()); + const lowercaseQueries: { [key: string]: string } = {}; + if (queries) { + const queryKeys: string[] = []; + for (const key in queries) { + if (queries.hasOwnProperty(key)) { + const lowercaseKey = key.toLowerCase(); + lowercaseQueries[lowercaseKey] = queries[key]; + queryKeys.push(lowercaseKey); + } + } + + queryKeys.sort(); + for (const key of queryKeys) { + canonicalizedResourceString += `\n${key}:${decodeURIComponent( + lowercaseQueries[key] + )}`; + } + } + + return canonicalizedResourceString; + } +} diff --git a/src/table/context/TableStorageContext.ts b/src/table/context/TableStorageContext.ts index 0c9b0dc81..23570f37a 100644 --- a/src/table/context/TableStorageContext.ts +++ b/src/table/context/TableStorageContext.ts @@ -17,6 +17,14 @@ export default class TableStorageContext extends Context { this.context.tableName = tableName; } + public get authenticationPath(): string | undefined { + return this.context.authenticationPath; + } + + public set authenticationPath(path: string | undefined) { + this.context.authenticationPath = path; + } + public get partitionKey(): string | undefined { return this.context.partitionKey; } diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index ef2003956..080a34d9d 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -48,6 +48,68 @@ export default class StorageErrorFactory { ); } + public static getInvalidOperation( + contextID: string, + message: string = "" + ): StorageError { + return new StorageError(400, "InvalidOperation", message, contextID); + } + + public static getAuthorizationSourceIPMismatch( + contextID: string + ): StorageError { + return new StorageError( + 403, + "AuthorizationSourceIPMismatch", + "This request is not authorized to perform this operation using this source IP {SourceIP}.", + contextID + ); + } + + public static getAuthorizationProtocolMismatch( + contextID: string + ): StorageError { + return new StorageError( + 403, + "AuthorizationProtocolMismatch", + "This request is not authorized to perform this operation using this protocol.", + contextID + ); + } + + public static getAuthorizationPermissionMismatch( + contextID: string + ): StorageError { + return new StorageError( + 403, + "AuthorizationPermissionMismatch", + "This request is not authorized to perform this operation using this permission.", + contextID + ); + } + + public static getAuthorizationServiceMismatch( + contextID: string + ): StorageError { + return new StorageError( + 403, + "AuthorizationServiceMismatch", + "This request is not authorized to perform this operation using this service.", + contextID + ); + } + + public static getAuthorizationResourceTypeMismatch( + contextID: string + ): StorageError { + return new StorageError( + 403, + "AuthorizationResourceTypeMismatch", + "This request is not authorized to perform this operation using this resource type.", + contextID + ); + } + public static getAccountNameEmpty(context: Context): StorageError { return new StorageError( 400, @@ -70,6 +132,16 @@ export default class StorageErrorFactory { ); } + public static getAuthorizationFailure(contextID: string): StorageError { + return new StorageError( + 403, + "AuthorizationFailure", + // tslint:disable-next-line:max-line-length + "Server failed to authenticate the request. Make sure the value of the Authorization header is formed correctly including the signature.", + contextID + ); + } + public static getEntityNotExist(context: Context): StorageError { return new StorageError( 409, diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index b29cc6018..362900c4f 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -1,4 +1,5 @@ import BufferStream from "../../common/utils/BufferStream"; +import { newEtag } from "../../common/utils/utils"; import TableStorageContext from "../context/TableStorageContext"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; @@ -16,7 +17,6 @@ import { RETURN_NO_CONTENT, TABLE_API_VERSION } from "../utils/constants"; -import { newEtag } from "../utils/utils"; import BaseHandler from "./BaseHandler"; export default class TableHandler extends BaseHandler implements ITableHandler { diff --git a/src/table/middleware/AuthenticationMiddlewareFactory.ts b/src/table/middleware/AuthenticationMiddlewareFactory.ts new file mode 100644 index 000000000..f90766cfb --- /dev/null +++ b/src/table/middleware/AuthenticationMiddlewareFactory.ts @@ -0,0 +1,60 @@ +import { NextFunction, Request, RequestHandler, Response } from "express"; + +import ILogger from "../../common/ILogger"; +import IAuthenticator from "../authentication/IAuthenticator"; +import TableStorageContext from "../context/TableStorageContext"; +import StorageErrorFactory from "../errors/StorageErrorFactory"; +import ExpressRequestAdapter from "../generated/ExpressRequestAdapter"; +import { DEFAULT_TABLE_CONTEXT_PATH } from "../utils/constants"; + +export default class AuthenticationMiddlewareFactory { + constructor(private readonly logger: ILogger) {} + + public createAuthenticationMiddleware( + authenticators: IAuthenticator[] + ): RequestHandler { + return (req: Request, res: Response, next: NextFunction) => { + const context = new TableStorageContext( + res.locals, + DEFAULT_TABLE_CONTEXT_PATH + ); + this.authenticate(req, res, authenticators) + .then(pass => { + if (pass) { + next(); + } else { + next( + StorageErrorFactory.getAuthorizationFailure(context.contextID!) + ); + } + }) + .catch(next); + }; + } + + private async authenticate( + req: Request, + res: Response, + authenticators: IAuthenticator[] + ): Promise { + const request = new ExpressRequestAdapter(req); + const context = new TableStorageContext( + res.locals, + DEFAULT_TABLE_CONTEXT_PATH + ); + + this.logger.verbose( + `AuthenticationMiddlewareFactory:createAuthenticationMiddleware() Validating authentications.`, + context.contextID + ); + + let pass: boolean | undefined = false; + for (const authenticator of authenticators) { + pass = await authenticator.validate(request, context); + if (pass === true) { + return true; + } + } + return false; + } +} diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index 05fd403ef..29f84d170 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -134,6 +134,8 @@ export function tableStorageContextMiddleware( tableContext.account = account; + tableContext.authenticationPath = req.path; + // Emulator's URL pattern is like http://hostname[:port]/account/table // (or, alternatively, http[s]://account.localhost[:port]/table/) // Create a router to exclude account name from req.path, as url path in swagger doesn't include account diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index a837c6be2..732f8d78b 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -1,6 +1,6 @@ import { stat } from "fs"; import Loki from "lokijs"; -import { newEtag } from "../../blob/utils/utils"; +import { newEtag } from "../../common/utils/utils"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; import * as Models from "../generated/artifacts/models"; diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index df384855b..234313a9b 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -18,8 +18,14 @@ export const TABLE_API_VERSION = "2019-12-12"; export const HeaderConstants = { SERVER: "Server", VERSION: "3.8.0", - X_MS_VERSION: "x-ms-version", - APPLICATION_JSON: "application/json" + APPLICATION_JSON: "application/json", + AUTHORIZATION: "authorization", + CONTENT_MD5: "content-md5", + CONTENT_TYPE: "content-type", + CONTENT_LENGTH: "content-length", + DATE: "date", + X_MS_DATE: "x-ms-date", + X_MS_VERSION: "x-ms-version" }; export const NO_METADATA_ACCEPT = "application/json;odata=nometadata"; diff --git a/src/table/utils/utils.ts b/src/table/utils/utils.ts index 6da84ffcf..18cc1bda0 100644 --- a/src/table/utils/utils.ts +++ b/src/table/utils/utils.ts @@ -1,17 +1,5 @@ import StorageErrorFactory from "../errors/StorageErrorFactory"; - -export function newEtag(): string { - // Etag should match ^"0x[A-F0-9]{15,}"$ - // Date().getTime().toString(16) only has 11 digital - // so multiply a number between 70000-100000, can get a 16 based 15+ digital number - return ( - '"0x' + - (new Date().getTime() * Math.round(Math.random() * 30000 + 70000)) - .toString(16) - .toUpperCase() + - '"' - ); -} +import { HeaderConstants } from "./constants"; export function checkApiVersion( inputApiVersion: string, @@ -20,7 +8,7 @@ export function checkApiVersion( ): void { if (!validApiVersions.includes(inputApiVersion)) { throw StorageErrorFactory.getInvalidHeaderValue(requestId, { - HeaderName: "x-ms-version", + HeaderName: HeaderConstants.X_MS_VERSION, HeaderValue: inputApiVersion }); } diff --git a/tests/TableTestServerFactory.ts b/tests/TableTestServerFactory.ts new file mode 100644 index 000000000..af343bd1b --- /dev/null +++ b/tests/TableTestServerFactory.ts @@ -0,0 +1,35 @@ +import TableConfiguration from "../src/table/TableConfiguration"; +import TableServer from "../src/table/TableServer"; + +export default class TableTestServerFactory { + public createServer( + loose: boolean = false, + skipApiVersionCheck: boolean = false, + https: boolean = false, + oauth?: string + ): TableServer { + const port = 11002; + const host = "127.0.0.1"; + + const cert = https ? "tests/server.cert" : undefined; + const key = https ? "tests/server.key" : undefined; + + const lokiMetadataDBPath = "__test_db_table__.json"; + const config = new TableConfiguration( + host, + port, + lokiMetadataDBPath, + true, + undefined, + undefined, + "debug-test-table.log", + loose, + skipApiVersionCheck, + cert, + key, + undefined, + oauth + ); + return new TableServer(config); + } +} diff --git a/tests/blob/apis/appendblob.test.ts b/tests/blob/apis/appendblob.test.ts index cf871d1d0..7b82f5b40 100644 --- a/tests/blob/apis/appendblob.test.ts +++ b/tests/blob/apis/appendblob.test.ts @@ -11,8 +11,8 @@ import { import assert = require("assert"); import { BlobType } from "../../../src/blob/generated/artifacts/models"; -import { getMD5FromString } from "../../../src/blob/utils/utils"; import { configLogger } from "../../../src/common/Logger"; +import { getMD5FromString } from "../../../src/common/utils/utils"; import BlobTestServerFactory from "../../BlobTestServerFactory"; import { bodyToString, diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 17cd735a6..acfe71025 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -1,15 +1,16 @@ import * as assert from "assert"; import * as Azure from "azure-storage"; -import StorageError from "../../../src/blob/errors/StorageError"; import { configLogger } from "../../../src/common/Logger"; +import StorageError from "../../../src/table/errors/StorageError"; import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME, getUniqueName, - overrideRequest + overrideRequest, + restoreBuildRequestOptions } from "../../testutils"; // Set true to enable debug log @@ -42,9 +43,9 @@ describe("table Entity APIs test", () => { let tableName: string = getUniqueName("table"); const requestOverride = { headers: {} }; - overrideRequest(requestOverride, tableService); before(async () => { + overrideRequest(requestOverride, tableService); server = new TableServer(config); tableName = getUniqueName("table"); await server.start(); @@ -60,6 +61,7 @@ describe("table Entity APIs test", () => { after(async () => { await server.close(); + restoreBuildRequestOptions(tableService); }); // Simple test in here until we have the full set checked in, as we need diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index d6e4ab7ff..5a39d7fca 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -12,7 +12,8 @@ import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME, getUniqueName, - overrideRequest + overrideRequest, + restoreBuildRequestOptions } from "../../testutils"; // Set true to enable debug log @@ -45,9 +46,9 @@ describe("table APIs test", () => { let tableName: string = getUniqueName("table"); const requestOverride = { headers: {} }; - overrideRequest(requestOverride, tableService); before(async () => { + overrideRequest(requestOverride, tableService); server = new TableServer(config); tableName = getUniqueName("table"); await server.start(); @@ -55,6 +56,7 @@ describe("table APIs test", () => { after(async () => { await server.close(); + restoreBuildRequestOptions(tableService); }); it("createTable, prefer=return-no-content, accept=application/json;odata=minimalmetadata @loki", done => { diff --git a/tests/table/sas.test.ts b/tests/table/sas.test.ts new file mode 100644 index 000000000..29cfdedf9 --- /dev/null +++ b/tests/table/sas.test.ts @@ -0,0 +1,257 @@ +import * as assert from "assert"; + +import * as Azure from "azure-storage"; +import { configLogger } from "../../src/common/Logger"; +import { TableSASPermission } from "../../src/table/authentication/TableSASPermissions"; +import StorageError from "../../src/table/errors/StorageError"; +import TableServer from "../../src/table/TableServer"; +import TableTestServerFactory from "../TableTestServerFactory"; +import { + EMULATOR_ACCOUNT_KEY, + EMULATOR_ACCOUNT_NAME, + getUniqueName +} from "../testutils"; + +// Set true to enable debug log +configLogger(false); + +describe("Shared Access Signature (SAS) authentication", () => { + const protocol = "http"; + const tableFactory = new TableTestServerFactory(); + + const server: TableServer = tableFactory.createServer(); + + const baseURL = `${protocol}://${server.host}:${server.port}/${EMULATOR_ACCOUNT_NAME}`; + const connectionString = + `DefaultEndpointsProtocol=${protocol};AccountName=${EMULATOR_ACCOUNT_NAME};` + + `AccountKey=${EMULATOR_ACCOUNT_KEY};TableEndpoint=${baseURL};`; + + // used to generate SAS + const tableService = Azure.createTableService(connectionString); + + const tableName: string = getUniqueName("table"); + + function sasPeriod(start: number, end: number) { + const now = new Date(); + const expiry = new Date(now); + now.setMinutes(now.getMinutes() + start); + expiry.setMinutes(expiry.getMinutes() + end); + return { Start: now, Expiry: expiry }; + } + + function getSasService(policy: Azure.TableService.TableAccessPolicy) { + const sas = tableService.generateSharedAccessSignature(tableName, { + AccessPolicy: policy + }); + + return Azure.createTableServiceWithSas(baseURL, sas); + } + + before(async () => { + await server.start(); + tableService.createTable(tableName, (error, result, response) => { + // created table for tests + }); + }); + + after(async () => { + await server.close(); + await server.clean(); + }); + + it("insertEntity with Query permission should not work @loki", done => { + const expiry = new Date(); + expiry.setMinutes(expiry.getMinutes() + 5); // Skip clock skew with server + + const sas = tableService.generateSharedAccessSignature(tableName, { + AccessPolicy: { + Permissions: TableSASPermission.Query, + Expiry: expiry + } + }); + + const sasService = Azure.createTableServiceWithSas(baseURL, sas); + + const entity = { + PartitionKey: "part1", + RowKey: "row1", + myValue: "value1" + }; + sasService.insertEntity(tableName, entity, (error, result, response) => { + assert.equal(response.statusCode, 403); + done(); + }); + }); + + it("insertEntity with Add permission should work @loki", done => { + const expiry = new Date(); + expiry.setMinutes(expiry.getMinutes() + 5); // Skip clock skew with server + + const sas = tableService.generateSharedAccessSignature(tableName, { + AccessPolicy: { Permissions: TableSASPermission.Add, Expiry: expiry } + }); + + const sasService = Azure.createTableServiceWithSas(baseURL, sas); + + const entity = { + PartitionKey: "part1", + RowKey: "row1", + myValue: "value1" + }; + sasService.insertEntity(tableName, entity, (error, result, response) => { + assert.equal(response.statusCode, 204); + done(); + }); + }); + + it("insertEntity Add permission should work @loki", done => { + const sasService = getSasService({ + Permissions: TableSASPermission.Add, + ...sasPeriod(-1, 5) + }); + + const entity = { + PartitionKey: "part1", + RowKey: "row2", + myValue: "value2" + }; + + sasService.insertEntity(tableName, entity, (error, result, response) => { + assert.equal(response.statusCode, 204); + done(); + }); + }); + + it("insertEntity expired Add permission should not work @loki", done => { + const sasService = getSasService({ + Permissions: TableSASPermission.Add, + ...sasPeriod(-10, -5) + }); + + const entity = { + PartitionKey: "part1", + RowKey: "row1", + myValue: "value1" + }; + + sasService.insertEntity(tableName, entity, (error, result, response) => { + assert.equal(response.statusCode, 403); + done(); + }); + }); + + it("deleteEntity with Delete permission should work @loki", done => { + const sasService = getSasService({ + Permissions: TableSASPermission.Delete, + ...sasPeriod(0, 5) + }); + + const entity = { + PartitionKey: "part1", + RowKey: "row1", + myValue: "value1" + }; + + sasService.deleteEntity(tableName, entity, (error, response) => { + assert.equal(response.statusCode, 204); + done(); + }); + }); + + it("deleteEntity with Add permission should not work @loki", done => { + const sasService = getSasService({ + Permissions: TableSASPermission.Add, + ...sasPeriod(0, 5) + }); + + const entity = { + PartitionKey: "part1", + RowKey: "row1", + myValue: "value1" + }; + + sasService.deleteEntity(tableName, entity, (error, response) => { + assert.equal(response.statusCode, 403); + done(); + }); + }); + + it("Update an Entity that exists, @loki", done => { + const sasService = getSasService({ + Permissions: TableSASPermission.Add + TableSASPermission.Update, + ...sasPeriod(0, 5) + }); + + const entityInsert = { + PartitionKey: "part1", + RowKey: "row3", + myValue: "oldValue" + }; + sasService.insertEntity( + tableName, + entityInsert, + (error, result, insertresponse) => { + if (!error) { + sasService.replaceEntity( + tableName, + { PartitionKey: "part1", RowKey: "row3", myValue: "newValue" }, + (updateError, updateResult, updateResponse) => { + if (!updateError) { + assert.equal(updateResponse.statusCode, 204); // Precondition succeeded + done(); + } else { + assert.ifError(updateError); + done(); + } + } + ); + } else { + assert.ifError(error); + done(); + } + } + ); + }); + + it("Update an Entity without update permission, @loki", done => { + const sasService = getSasService({ + Permissions: TableSASPermission.Add, + ...sasPeriod(0, 5) + }); + + sasService.replaceEntity( + tableName, + { PartitionKey: "part1", RowKey: "row4", myValue: "newValue" }, + (updateError, updateResult, updateResponse) => { + const castUpdateStatusCode = (updateError as StorageError).statusCode; + if (updateError) { + assert.equal(castUpdateStatusCode, 403); + done(); + } else { + assert.fail("Test failed to throw the right Error" + updateError); + } + } + ); + }); + + it("Update an Entity that does not exist, @loki", done => { + const sasService = getSasService({ + Permissions: TableSASPermission.Update, + ...sasPeriod(0, 5) + }); + + sasService.replaceEntity( + tableName, + { PartitionKey: "part1", RowKey: "row4", myValue: "newValue" }, + (updateError, updateResult, updateResponse) => { + const castUpdateStatusCode = (updateError as StorageError).statusCode; + if (updateError) { + assert.equal(castUpdateStatusCode, 409); + done(); + } else { + assert.fail("Test failed to throw the right Error" + updateError); + } + } + ); + }); +}); diff --git a/tests/testutils.ts b/tests/testutils.ts index 903e12541..ff3068aad 100644 --- a/tests/testutils.ts +++ b/tests/testutils.ts @@ -200,16 +200,31 @@ export function generateJWTToken( return token; } +export function restoreBuildRequestOptions(service: any) { + if ((service as any).__proto__.__proto__.__original_buildRequestOptions) { + // tslint:disable-next-line: max-line-length + (service as any).__proto__.__proto__._buildRequestOptions = (service as any).__proto__.__proto__.__original_buildRequestOptions; + } +} export function overrideRequest( override: { headers: { [key: string]: string }; } = { headers: {} }, - serivce: StorageServiceClient + service: StorageServiceClient ) { - const _buildRequestOptions = (serivce as any).__proto__.__proto__._buildRequestOptions.bind( - serivce - ); - (serivce as any).__proto__.__proto__._buildRequestOptions = ( + const hasOriginal = !!(service as any).__proto__.__proto__ + .__original_buildRequestOptions; + + const original = hasOriginal + ? (service as any).__proto__.__proto__.__original_buildRequestOptions + : (service as any).__proto__.__proto__._buildRequestOptions; + + if (!hasOriginal) { + (service as any).__proto__.__proto__.__original_buildRequestOptions = original; + } + + const _buildRequestOptions = original.bind(service); + (service as any).__proto__.__proto__._buildRequestOptions = ( webResource: any, body: any, options: any, From 936e698195d6586b54e9cbe0c08e293ecf860260 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Mon, 12 Oct 2020 17:11:18 +0800 Subject: [PATCH 18/57] Add Table Batch API (#594) * Add Table Batch API * Add table into CI --- azure-pipelines.yml | 1 + package.json | 2 +- .../OperationAccountSASPermission.ts | 24 +- .../OperationTableSASPermission.ts | 9 + src/table/generated/artifacts/mappers.ts | 40 +++ src/table/generated/artifacts/models.ts | 91 ++++++- src/table/generated/artifacts/operation.ts | 1 + src/table/generated/artifacts/parameters.ts | 20 ++ .../generated/artifacts/specifications.ts | 228 ++++++++++++++---- src/table/generated/handlers/ITableHandler.ts | 1 + .../generated/handlers/handlerMappers.ts | 10 + src/table/handlers/TableHandler.ts | 20 +- swagger/table.md | 4 +- swagger/table/table.json | 100 ++++++++ 14 files changed, 483 insertions(+), 68 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 5787e5ab3..7671de4c1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -6,6 +6,7 @@ trigger: - master + - table - dev jobs: diff --git a/package.json b/package.json index 3265d75f0..3c6c9129a 100644 --- a/package.json +++ b/package.json @@ -218,7 +218,7 @@ "build:autorest:debug": "autorest ./swagger/blob.md --typescript --typescript.debugger --use=E:/GitHub/XiaoningLiu/autorest.typescript.server", "build:autorest:blob": "autorest ./swagger/blob.md --typescript --use=S:/GitHub/XiaoningLiu/autorest.typescript.server", "build:autorest:queue": "autorest ./swagger/queue.md --typescript --use=S:/GitHub/XiaoningLiu/autorest.typescript.server", - "build:autorest:table": "autorest ./swagger/table.md --typescript --use=/Users/isabella/Desktop/AzureStorage/autorest.typescript.server", + "build:autorest:table": "autorest ./swagger/table.md --typescript --use=S:/GitHub/XiaoningLiu/autorest.typescript.server", "watch": "tsc -watch -p ./", "blob": "node -r ts-node/register src/blob/main.ts", "queue": "node -r ts-node/register src/queue/main.ts", diff --git a/src/table/authentication/OperationAccountSASPermission.ts b/src/table/authentication/OperationAccountSASPermission.ts index 266d5308f..3b3e00a2a 100644 --- a/src/table/authentication/OperationAccountSASPermission.ts +++ b/src/table/authentication/OperationAccountSASPermission.ts @@ -1,8 +1,4 @@ -import { - AccountSASPermissions, - AccountSASResourceTypes, - AccountSASServices -} from "@azure/storage-blob"; +import { AccountSASPermissions, AccountSASResourceTypes, AccountSASServices } from "@azure/storage-blob"; import Operation from "../generated/artifacts/operation"; import { AccountSASPermission } from "./AccountSASPermissions"; @@ -202,4 +198,22 @@ OPERATION_ACCOUNT_SAS_PERMISSIONS.set( ) ); +OPERATION_ACCOUNT_SAS_PERMISSIONS.set( + Operation.Table_Batch, + new OperationAccountSASPermission( + AccountSASService.Table, + AccountSASResourceType.Object + + AccountSASResourceType.Service + + AccountSASResourceType.Container, + AccountSASPermission.Delete + + AccountSASPermission.Add + + AccountSASPermission.Create + + AccountSASPermission.List + + AccountSASPermission.Process + + AccountSASPermission.Read + + AccountSASPermission.Update + + AccountSASPermission.Write + ) +); + export default OPERATION_ACCOUNT_SAS_PERMISSIONS; diff --git a/src/table/authentication/OperationTableSASPermission.ts b/src/table/authentication/OperationTableSASPermission.ts index 5d4df7b55..490642f09 100644 --- a/src/table/authentication/OperationTableSASPermission.ts +++ b/src/table/authentication/OperationTableSASPermission.ts @@ -129,3 +129,12 @@ OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( Operation.Table_MergeEntityWithMerge, new OperationTableSASPermission(TableSASPermission.Update) ); +OPERATION_TABLE_SAS_TABLE_PERMISSIONS.set( + Operation.Table_Batch, + new OperationTableSASPermission( + TableSASPermission.Add + + TableSASPermission.Delete + + TableSASPermission.Query + + TableSASPermission.Update + ) +); diff --git a/src/table/generated/artifacts/mappers.ts b/src/table/generated/artifacts/mappers.ts index 099354f1e..c9903892d 100644 --- a/src/table/generated/artifacts/mappers.ts +++ b/src/table/generated/artifacts/mappers.ts @@ -639,6 +639,46 @@ export const TableCreateHeaders: msRest.CompositeMapper = { } }; +export const TableBatchHeaders: msRest.CompositeMapper = { + serializedName: "table-batch-headers", + type: { + name: "Composite", + className: "TableBatchHeaders", + modelProperties: { + contentType: { + serializedName: "content-type", + type: { + name: "String" + } + }, + requestId: { + serializedName: "x-ms-request-id", + type: { + name: "String" + } + }, + version: { + serializedName: "x-ms-version", + type: { + name: "String" + } + }, + date: { + serializedName: "date", + type: { + name: "DateTimeRfc1123" + } + }, + errorCode: { + serializedName: "x-ms-error-code", + type: { + name: "String" + } + } + } + } +}; + export const TableDeleteHeaders: msRest.CompositeMapper = { serializedName: "table-delete-headers", type: { diff --git a/src/table/generated/artifacts/models.ts b/src/table/generated/artifacts/models.ts index 3541c48b9..42092b017 100644 --- a/src/table/generated/artifacts/models.ts +++ b/src/table/generated/artifacts/models.ts @@ -366,6 +366,21 @@ export interface TableCreateOptionalParams { queryOptions?: QueryOptions; } +/** + * Optional Parameters. + */ +export interface TableBatchOptionalParams { + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + dataServiceVersion?: DataServiceVersion2; +} + /** * Optional Parameters. */ @@ -393,7 +408,7 @@ export interface TableQueryEntitiesOptionalParams { /** * Specifies the data service version. Possible values include: '3.0' */ - dataServiceVersion?: DataServiceVersion2; + dataServiceVersion?: DataServiceVersion3; /** * An entity query continuation token from a previous call. */ @@ -424,7 +439,7 @@ export interface TableQueryEntitiesWithPartitionAndRowKeyOptionalParams { /** * Specifies the data service version. Possible values include: '3.0' */ - dataServiceVersion?: DataServiceVersion3; + dataServiceVersion?: DataServiceVersion4; /** * Additional parameters for the operation */ @@ -447,7 +462,7 @@ export interface TableUpdateEntityOptionalParams { /** * Specifies the data service version. Possible values include: '3.0' */ - dataServiceVersion?: DataServiceVersion4; + dataServiceVersion?: DataServiceVersion5; /** * The properties for the table entity. */ @@ -481,7 +496,7 @@ export interface TableMergeEntityOptionalParams { /** * Specifies the data service version. Possible values include: '3.0' */ - dataServiceVersion?: DataServiceVersion5; + dataServiceVersion?: DataServiceVersion6; /** * The properties for the table entity. */ @@ -515,7 +530,7 @@ export interface TableDeleteEntityOptionalParams { /** * Specifies the data service version. Possible values include: '3.0' */ - dataServiceVersion?: DataServiceVersion6; + dataServiceVersion?: DataServiceVersion7; /** * Additional parameters for the operation */ @@ -538,7 +553,7 @@ export interface TableMergeEntityWithMergeOptionalParams { /** * Specifies the data service version. Possible values include: '3.0' */ - dataServiceVersion?: DataServiceVersion7; + dataServiceVersion?: DataServiceVersion8; /** * The properties for the table entity. */ @@ -572,7 +587,7 @@ export interface TableInsertEntityOptionalParams { /** * Specifies the data service version. Possible values include: '3.0' */ - dataServiceVersion?: DataServiceVersion8; + dataServiceVersion?: DataServiceVersion9; /** * The properties for the table entity. */ @@ -731,6 +746,33 @@ export interface TableCreateHeaders { errorCode?: string; } +/** + * Defines headers for Batch operation. + */ +export interface TableBatchHeaders { + /** + * The media type of the body of the response. For batch requests, this is multipart/mixed; + * boundary=batchresponse_GUID + */ + contentType?: string; + /** + * This header uniquely identifies the request that was made and can be used for troubleshooting + * the request. + */ + requestId?: string; + /** + * Indicates the version of the Blob service used to execute the request. This header is returned + * for requests made against version 2009-09-19 and above. + */ + version?: string; + /** + * UTC date/time value generated by the service that indicates the time at which the response was + * initiated. + */ + date?: Date; + errorCode?: string; +} + /** * Defines headers for Delete operation. */ @@ -1260,6 +1302,16 @@ export enum DataServiceVersion8 { ThreeFullStopZero = '3.0', } +/** + * Defines values for DataServiceVersion9. + * Possible values include: '3.0' + * @readonly + * @enum {string} + */ +export enum DataServiceVersion9 { + ThreeFullStopZero = '3.0', +} + /** * Defines values for Version1. * Possible values include: '2019-02-02' @@ -1410,6 +1462,16 @@ export enum Version15 { TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', } +/** + * Defines values for Version16. + * Possible values include: '2019-02-02' + * @readonly + * @enum {string} + */ +export enum Version16 { + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', +} + /** * Contains response data for the query operation. */ @@ -1430,6 +1492,21 @@ export type TableCreateResponse = TableResponse & TableCreateHeaders & { statusCode: 201 | 204; }; +/** + * Contains response data for the batch operation. + */ +export type TableBatchResponse = TableBatchHeaders & { + /** + * The response body as a node.js Readable stream. + */ + body?: NodeJS.ReadableStream; +} & { + /** + * The response status code. + */ + statusCode: 202; +}; + /** * Contains response data for the deleteMethod operation. */ diff --git a/src/table/generated/artifacts/operation.ts b/src/table/generated/artifacts/operation.ts index 17d30a576..864803243 100644 --- a/src/table/generated/artifacts/operation.ts +++ b/src/table/generated/artifacts/operation.ts @@ -9,6 +9,7 @@ export enum Operation { Table_Query, Table_Create, + Table_Batch, Table_Delete, Table_QueryEntities, Table_QueryEntitiesWithPartitionAndRowKey, diff --git a/src/table/generated/artifacts/parameters.ts b/src/table/generated/artifacts/parameters.ts index 920ab25ab..0952a8f5a 100644 --- a/src/table/generated/artifacts/parameters.ts +++ b/src/table/generated/artifacts/parameters.ts @@ -49,6 +49,16 @@ export const comp2: msRest.OperationQueryParameter = { } } }; +export const contentLength: msRest.OperationParameter = { + parameterPath: "contentLength", + mapper: { + required: true, + serializedName: "Content-Length", + type: { + name: "Number" + } + } +}; export const dataServiceVersion: msRest.OperationParameter = { parameterPath: [ "options", @@ -109,6 +119,16 @@ export const ifMatch1: msRest.OperationParameter = { } } }; +export const multipartContentType: msRest.OperationParameter = { + parameterPath: "multipartContentType", + mapper: { + required: true, + serializedName: "Content-Type", + type: { + name: "String" + } + } +}; export const nextPartitionKey: msRest.OperationQueryParameter = { parameterPath: [ "options", diff --git a/src/table/generated/artifacts/specifications.ts b/src/table/generated/artifacts/specifications.ts index 278ba7e56..943fc2a11 100644 --- a/src/table/generated/artifacts/specifications.ts +++ b/src/table/generated/artifacts/specifications.ts @@ -20,7 +20,9 @@ const serializer = new msRest.Serializer(Mappers, true); const tableQueryOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "Tables", - urlParameters: [Parameters.url], + urlParameters: [ + Parameters.url + ], queryParameters: [ Parameters.nextTableName, Parameters.format, @@ -47,8 +49,12 @@ const tableQueryOperationSpec: msRest.OperationSpec = { const tableCreateOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "Tables", - urlParameters: [Parameters.url], - queryParameters: [Parameters.format], + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -79,11 +85,59 @@ const tableCreateOperationSpec: msRest.OperationSpec = { serializer }; +const tableBatchOperationSpec: msRest.OperationSpec = { + httpMethod: "POST", + path: "$batch", + urlParameters: [ + Parameters.url + ], + headerParameters: [ + Parameters.version, + Parameters.requestId, + Parameters.dataServiceVersion, + Parameters.multipartContentType, + Parameters.contentLength + ], + requestBody: { + parameterPath: "body", + mapper: { + required: true, + serializedName: "body", + type: { + name: "Stream" + } + } + }, + contentType: "application/json;odata=nometadata; charset=utf-8", + responses: { + 202: { + bodyMapper: { + serializedName: "Stream", + type: { + name: "Stream" + } + }, + headersMapper: Mappers.TableBatchHeaders + }, + default: { + bodyMapper: Mappers.TableServiceError + } + }, + isXML: true, + serializer +}; + const tableDeleteOperationSpec: msRest.OperationSpec = { httpMethod: "DELETE", path: "Tables('{table}')", - urlParameters: [Parameters.url, Parameters.table], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url, + Parameters.table + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], responses: { 204: { headersMapper: Mappers.TableDeleteHeaders @@ -99,7 +153,10 @@ const tableDeleteOperationSpec: msRest.OperationSpec = { const tableQueryEntitiesOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "{table}()", - urlParameters: [Parameters.url, Parameters.table], + urlParameters: [ + Parameters.url, + Parameters.table + ], queryParameters: [ Parameters.timeout, Parameters.nextPartitionKey, @@ -169,7 +226,10 @@ const tableUpdateEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [Parameters.timeout, Parameters.format], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -177,7 +237,10 @@ const tableUpdateEntityOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: ["options", "tableEntityProperties"], + parameterPath: [ + "options", + "tableEntityProperties" + ], mapper: { serializedName: "tableEntityProperties", type: { @@ -211,7 +274,10 @@ const tableMergeEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [Parameters.timeout, Parameters.format], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -219,7 +285,10 @@ const tableMergeEntityOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: ["options", "tableEntityProperties"], + parameterPath: [ + "options", + "tableEntityProperties" + ], mapper: { serializedName: "tableEntityProperties", type: { @@ -253,7 +322,10 @@ const tableDeleteEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [Parameters.timeout, Parameters.format], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -281,7 +353,10 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [Parameters.timeout, Parameters.format], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -289,7 +364,10 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: ["options", "tableEntityProperties"], + parameterPath: [ + "options", + "tableEntityProperties" + ], mapper: { serializedName: "tableEntityProperties", type: { @@ -317,8 +395,14 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { const tableInsertEntityOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "{table}", - urlParameters: [Parameters.url, Parameters.table], - queryParameters: [Parameters.timeout, Parameters.format], + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -326,7 +410,10 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { Parameters.responsePreference ], requestBody: { - parameterPath: ["options", "tableEntityProperties"], + parameterPath: [ + "options", + "tableEntityProperties" + ], mapper: { serializedName: "tableEntityProperties", type: { @@ -364,9 +451,18 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "{table}", - urlParameters: [Parameters.url, Parameters.table], - queryParameters: [Parameters.timeout, Parameters.comp0], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp0 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], responses: { 200: { bodyMapper: { @@ -395,11 +491,23 @@ const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { httpMethod: "PUT", path: "{table}", - urlParameters: [Parameters.url, Parameters.table], - queryParameters: [Parameters.timeout, Parameters.comp0], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp0 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], requestBody: { - parameterPath: ["options", "tableAcl"], + parameterPath: [ + "options", + "tableAcl" + ], mapper: { xmlName: "SignedIdentifiers", xmlElementName: "SignedIdentifier", @@ -431,9 +539,18 @@ const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { // specifications for new method group start const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { httpMethod: "PUT", - urlParameters: [Parameters.url], - queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp1], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp1 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], requestBody: { parameterPath: "tableServiceProperties", mapper: { @@ -456,9 +573,18 @@ const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { httpMethod: "GET", - urlParameters: [Parameters.url], - queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp1], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp1 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], responses: { 200: { bodyMapper: Mappers.TableServiceProperties, @@ -474,9 +600,18 @@ const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { const serviceGetStatisticsOperationSpec: msRest.OperationSpec = { httpMethod: "GET", - urlParameters: [Parameters.url], - queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp2], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp2 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], responses: { 200: { bodyMapper: Mappers.TableServiceStats, @@ -493,31 +628,18 @@ const serviceGetStatisticsOperationSpec: msRest.OperationSpec = { const Specifications: { [key: number]: msRest.OperationSpec } = {}; Specifications[Operation.Table_Query] = tableQueryOperationSpec; Specifications[Operation.Table_Create] = tableCreateOperationSpec; +Specifications[Operation.Table_Batch] = tableBatchOperationSpec; Specifications[Operation.Table_Delete] = tableDeleteOperationSpec; Specifications[Operation.Table_QueryEntities] = tableQueryEntitiesOperationSpec; -Specifications[ - Operation.Table_QueryEntitiesWithPartitionAndRowKey -] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; +Specifications[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; Specifications[Operation.Table_UpdateEntity] = tableUpdateEntityOperationSpec; Specifications[Operation.Table_MergeEntity] = tableMergeEntityOperationSpec; Specifications[Operation.Table_DeleteEntity] = tableDeleteEntityOperationSpec; -Specifications[ - Operation.Table_MergeEntityWithMerge -] = tableMergeEntityWithMergeOperationSpec; +Specifications[Operation.Table_MergeEntityWithMerge] = tableMergeEntityWithMergeOperationSpec; Specifications[Operation.Table_InsertEntity] = tableInsertEntityOperationSpec; -Specifications[ - Operation.Table_GetAccessPolicy -] = tableGetAccessPolicyOperationSpec; -Specifications[ - Operation.Table_SetAccessPolicy -] = tableSetAccessPolicyOperationSpec; -Specifications[ - Operation.Service_SetProperties -] = serviceSetPropertiesOperationSpec; -Specifications[ - Operation.Service_GetProperties -] = serviceGetPropertiesOperationSpec; -Specifications[ - Operation.Service_GetStatistics -] = serviceGetStatisticsOperationSpec; +Specifications[Operation.Table_GetAccessPolicy] = tableGetAccessPolicyOperationSpec; +Specifications[Operation.Table_SetAccessPolicy] = tableSetAccessPolicyOperationSpec; +Specifications[Operation.Service_SetProperties] = serviceSetPropertiesOperationSpec; +Specifications[Operation.Service_GetProperties] = serviceGetPropertiesOperationSpec; +Specifications[Operation.Service_GetStatistics] = serviceGetStatisticsOperationSpec; export default Specifications; diff --git a/src/table/generated/handlers/ITableHandler.ts b/src/table/generated/handlers/ITableHandler.ts index 9c5f2769e..2e2266c71 100644 --- a/src/table/generated/handlers/ITableHandler.ts +++ b/src/table/generated/handlers/ITableHandler.ts @@ -15,6 +15,7 @@ import Context from "../Context"; export default interface ITableHandler { query(options: Models.TableQueryOptionalParams, context: Context): Promise; create(tableProperties: Models.TableProperties, options: Models.TableCreateOptionalParams, context: Context): Promise; + batch(body: NodeJS.ReadableStream, multipartContentType: string, contentLength: number, options: Models.TableBatchOptionalParams, context: Context): Promise; delete(table: string, options: Models.TableDeleteMethodOptionalParams, context: Context): Promise; queryEntities(table: string, options: Models.TableQueryEntitiesOptionalParams, context: Context): Promise; queryEntitiesWithPartitionAndRowKey(table: string, partitionKey: string, rowKey: string, options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, context: Context): Promise; diff --git a/src/table/generated/handlers/handlerMappers.ts b/src/table/generated/handlers/handlerMappers.ts index f120788d5..abfdbc323 100644 --- a/src/table/generated/handlers/handlerMappers.ts +++ b/src/table/generated/handlers/handlerMappers.ts @@ -25,6 +25,16 @@ operationHandlerMapping[Operation.Table_Create] = { handler: "tableHandler", method: "create" }; +operationHandlerMapping[Operation.Table_Batch] = { + arguments: [ + "body", + "multipartContentType", + "contentLength", + "options" + ], + handler: "tableHandler", + method: "batch" +}; operationHandlerMapping[Operation.Table_Delete] = { arguments: [ "table", diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 362900c4f..653a5d0da 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -15,11 +15,29 @@ import { NO_METADATA_ACCEPT, RETURN_CONTENT, RETURN_NO_CONTENT, - TABLE_API_VERSION + TABLE_API_VERSION, } from "../utils/constants"; import BaseHandler from "./BaseHandler"; export default class TableHandler extends BaseHandler implements ITableHandler { + public async batch( + body: NodeJS.ReadableStream, + multipartContentType: string, + contentLength: number, + options: Models.TableBatchOptionalParams, + context: Context + ): Promise { + const tableCtx = new TableStorageContext(context); + // TODO: Implement batch operation logic here + return { + requestId: tableCtx.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode: 202, + body // Use incoming request body as Batch operation response body as demo + }; + } + public async create( tableProperties: Models.TableProperties, options: Models.TableCreateOptionalParams, diff --git a/swagger/table.md b/swagger/table.md index 0eb1f1724..693033ef1 100644 --- a/swagger/table.md +++ b/swagger/table.md @@ -90,4 +90,6 @@ directive: transform: > $.post = {...$.patch}; $.post.operationId = "Table_MergeEntityWithMerge" -``` \ No newline at end of file +``` + +### TODO: Move Table Batch swagger change here \ No newline at end of file diff --git a/swagger/table/table.json b/swagger/table/table.json index abc01960c..52828fd0f 100644 --- a/swagger/table/table.json +++ b/swagger/table/table.json @@ -220,6 +220,77 @@ } } }, + "/$batch": { + "post": { + "tags": [ + "table" + ], + "operationId": "Table_Batch", + "description": "Entity group transactions.", + "parameters": [ + { + "$ref": "#/parameters/Body" + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/ClientRequestId" + }, + { + "$ref": "#/parameters/DataServiceVersionParameter" + }, + { + "$ref": "#/parameters/MultipartContentType" + }, + { + "$ref": "#/parameters/ContentLength" + } + ], + "responses": { + "202": { + "description": "Accepted.", + "headers": { + "Content-Type": { + "type": "string", + "description": "The media type of the body of the response. For batch requests, this is multipart/mixed; boundary=batchresponse_GUID" + }, + "x-ms-request-id": { + "x-ms-client-name": "RequestId", + "type": "string", + "description": "This header uniquely identifies the request that was made and can be used for troubleshooting the request." + }, + "x-ms-version": { + "x-ms-client-name": "Version", + "type": "string", + "description": "Indicates the version of the Blob service used to execute the request. This header is returned for requests made against version 2009-09-19 and above." + }, + "Date": { + "type": "string", + "format": "date-time-rfc1123", + "description": "UTC date/time value generated by the service that indicates the time at which the response was initiated." + } + }, + "schema": { + "type": "object", + "format": "file" + } + }, + "default": { + "description": "Failure", + "headers": { + "x-ms-error-code": { + "x-ms-client-name": "ErrorCode", + "type": "string" + } + }, + "schema": { + "$ref": "#/definitions/TableServiceError" + } + } + } + } + }, "/Tables('{table}')": { "delete": { "tags": [ @@ -1908,6 +1979,35 @@ "type": "string", "x-ms-parameter-location": "method", "description": "The row key of the entity." + }, + "MultipartContentType": { + "name": "Content-Type", + "x-ms-client-name": "multipartContentType", + "in": "header", + "required": true, + "type": "string", + "x-ms-parameter-location": "method", + "description": "Required. The value of this header must be multipart/mixed with a batch boundary. Example header value: multipart/mixed; boundary=batch_" + }, + "Body": { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "format": "file" + }, + "x-ms-parameter-location": "method", + "description": "Initial data" + }, + "ContentLength": { + "name": "Content-Length", + "in": "header", + "required": true, + "type": "integer", + "format": "int64", + "x-ms-parameter-location": "method", + "description": "The length of the request." } } } From 6f6287727889f17f0f5302da1b7cd5e64cfdcfc6 Mon Sep 17 00:00:00 2001 From: Yi Lyu <41231856+isabella0428@users.noreply.github.com> Date: Thu, 5 Nov 2020 15:24:17 +0800 Subject: [PATCH 19/57] Add queryEntities (#551) * modify post verb to merge * Fix CI * Add queryEntities Co-authored-by: xiaonlimsft --- .vscode/launch.json | 2 + src/table/errors/StorageErrorFactory.ts | 19 +- .../generated/artifacts/specifications.ts | 185 ++++---------- src/table/handlers/TableHandler.ts | 234 ++++++++++++++---- .../tableStorageContext.middleware.ts | 6 + src/table/persistence/ITableMetadataStore.ts | 7 +- .../persistence/LokiTableMetadataStore.ts | 160 +++++++++++- src/table/utils/constants.ts | 3 + 8 files changed, 430 insertions(+), 186 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 88cafd4a0..6f6f7e2b0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,6 +14,8 @@ "env": { "AZURITE_ACCOUNTS": "" }, + "skipFiles": ["node_modules/*/**", "/*/**"], + "outputCapture": "std" }, { diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 080a34d9d..28a0b9a78 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -186,6 +186,17 @@ export default class StorageErrorFactory { ); } + public static getPreconditionFailed(context: Context): StorageError { + return new StorageError( + 412, + "UpdateConditionNotSatisfied", + "The update condition specified in the request was not satisfied.", + context.contextID || defaultID, + undefined, + context + ); + } + public static getTableNotFound(context: Context): StorageError { return new StorageError( 404, @@ -208,11 +219,11 @@ export default class StorageErrorFactory { ); } - public static getPreconditionFailed(context: Context): StorageError { + public static getQueryConditionInvalid(context: Context): StorageError { return new StorageError( - 412, - "UpdateConditionNotSatisfied", - "The update condition specified in the request was not satisfied.", + 400, + "queryConditionsIncorrect", + "The query condition specified in the request was invalid.", context.contextID || defaultID, undefined, context diff --git a/src/table/generated/artifacts/specifications.ts b/src/table/generated/artifacts/specifications.ts index 943fc2a11..2867785a5 100644 --- a/src/table/generated/artifacts/specifications.ts +++ b/src/table/generated/artifacts/specifications.ts @@ -20,9 +20,7 @@ const serializer = new msRest.Serializer(Mappers, true); const tableQueryOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "Tables", - urlParameters: [ - Parameters.url - ], + urlParameters: [Parameters.url], queryParameters: [ Parameters.nextTableName, Parameters.format, @@ -49,12 +47,8 @@ const tableQueryOperationSpec: msRest.OperationSpec = { const tableCreateOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "Tables", - urlParameters: [ - Parameters.url - ], - queryParameters: [ - Parameters.format - ], + urlParameters: [Parameters.url], + queryParameters: [Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -130,14 +124,8 @@ const tableBatchOperationSpec: msRest.OperationSpec = { const tableDeleteOperationSpec: msRest.OperationSpec = { httpMethod: "DELETE", path: "Tables('{table}')", - urlParameters: [ - Parameters.url, - Parameters.table - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url, Parameters.table], + headerParameters: [Parameters.version, Parameters.requestId], responses: { 204: { headersMapper: Mappers.TableDeleteHeaders @@ -153,10 +141,7 @@ const tableDeleteOperationSpec: msRest.OperationSpec = { const tableQueryEntitiesOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "{table}()", - urlParameters: [ - Parameters.url, - Parameters.table - ], + urlParameters: [Parameters.url, Parameters.table], queryParameters: [ Parameters.timeout, Parameters.nextPartitionKey, @@ -226,10 +211,7 @@ const tableUpdateEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -237,10 +219,7 @@ const tableUpdateEntityOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: [ - "options", - "tableEntityProperties" - ], + parameterPath: ["options", "tableEntityProperties"], mapper: { serializedName: "tableEntityProperties", type: { @@ -274,10 +253,7 @@ const tableMergeEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -285,10 +261,7 @@ const tableMergeEntityOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: [ - "options", - "tableEntityProperties" - ], + parameterPath: ["options", "tableEntityProperties"], mapper: { serializedName: "tableEntityProperties", type: { @@ -322,10 +295,7 @@ const tableDeleteEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -353,10 +323,7 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -364,10 +331,7 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: [ - "options", - "tableEntityProperties" - ], + parameterPath: ["options", "tableEntityProperties"], mapper: { serializedName: "tableEntityProperties", type: { @@ -395,14 +359,8 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { const tableInsertEntityOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "{table}", - urlParameters: [ - Parameters.url, - Parameters.table - ], - queryParameters: [ - Parameters.timeout, - Parameters.format - ], + urlParameters: [Parameters.url, Parameters.table], + queryParameters: [Parameters.timeout, Parameters.format], headerParameters: [ Parameters.version, Parameters.requestId, @@ -410,10 +368,7 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { Parameters.responsePreference ], requestBody: { - parameterPath: [ - "options", - "tableEntityProperties" - ], + parameterPath: ["options", "tableEntityProperties"], mapper: { serializedName: "tableEntityProperties", type: { @@ -451,18 +406,9 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "{table}", - urlParameters: [ - Parameters.url, - Parameters.table - ], - queryParameters: [ - Parameters.timeout, - Parameters.comp0 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url, Parameters.table], + queryParameters: [Parameters.timeout, Parameters.comp0], + headerParameters: [Parameters.version, Parameters.requestId], responses: { 200: { bodyMapper: { @@ -491,23 +437,11 @@ const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { httpMethod: "PUT", path: "{table}", - urlParameters: [ - Parameters.url, - Parameters.table - ], - queryParameters: [ - Parameters.timeout, - Parameters.comp0 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url, Parameters.table], + queryParameters: [Parameters.timeout, Parameters.comp0], + headerParameters: [Parameters.version, Parameters.requestId], requestBody: { - parameterPath: [ - "options", - "tableAcl" - ], + parameterPath: ["options", "tableAcl"], mapper: { xmlName: "SignedIdentifiers", xmlElementName: "SignedIdentifier", @@ -539,18 +473,9 @@ const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { // specifications for new method group start const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { httpMethod: "PUT", - urlParameters: [ - Parameters.url - ], - queryParameters: [ - Parameters.timeout, - Parameters.restype, - Parameters.comp1 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url], + queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp1], + headerParameters: [Parameters.version, Parameters.requestId], requestBody: { parameterPath: "tableServiceProperties", mapper: { @@ -573,18 +498,9 @@ const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { httpMethod: "GET", - urlParameters: [ - Parameters.url - ], - queryParameters: [ - Parameters.timeout, - Parameters.restype, - Parameters.comp1 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url], + queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp1], + headerParameters: [Parameters.version, Parameters.requestId], responses: { 200: { bodyMapper: Mappers.TableServiceProperties, @@ -600,18 +516,9 @@ const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { const serviceGetStatisticsOperationSpec: msRest.OperationSpec = { httpMethod: "GET", - urlParameters: [ - Parameters.url - ], - queryParameters: [ - Parameters.timeout, - Parameters.restype, - Parameters.comp2 - ], - headerParameters: [ - Parameters.version, - Parameters.requestId - ], + urlParameters: [Parameters.url], + queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp2], + headerParameters: [Parameters.version, Parameters.requestId], responses: { 200: { bodyMapper: Mappers.TableServiceStats, @@ -631,15 +538,29 @@ Specifications[Operation.Table_Create] = tableCreateOperationSpec; Specifications[Operation.Table_Batch] = tableBatchOperationSpec; Specifications[Operation.Table_Delete] = tableDeleteOperationSpec; Specifications[Operation.Table_QueryEntities] = tableQueryEntitiesOperationSpec; -Specifications[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; +Specifications[ + Operation.Table_QueryEntitiesWithPartitionAndRowKey +] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; Specifications[Operation.Table_UpdateEntity] = tableUpdateEntityOperationSpec; Specifications[Operation.Table_MergeEntity] = tableMergeEntityOperationSpec; Specifications[Operation.Table_DeleteEntity] = tableDeleteEntityOperationSpec; -Specifications[Operation.Table_MergeEntityWithMerge] = tableMergeEntityWithMergeOperationSpec; +Specifications[ + Operation.Table_MergeEntityWithMerge +] = tableMergeEntityWithMergeOperationSpec; Specifications[Operation.Table_InsertEntity] = tableInsertEntityOperationSpec; -Specifications[Operation.Table_GetAccessPolicy] = tableGetAccessPolicyOperationSpec; -Specifications[Operation.Table_SetAccessPolicy] = tableSetAccessPolicyOperationSpec; -Specifications[Operation.Service_SetProperties] = serviceSetPropertiesOperationSpec; -Specifications[Operation.Service_GetProperties] = serviceGetPropertiesOperationSpec; -Specifications[Operation.Service_GetStatistics] = serviceGetStatisticsOperationSpec; +Specifications[ + Operation.Table_GetAccessPolicy +] = tableGetAccessPolicyOperationSpec; +Specifications[ + Operation.Table_SetAccessPolicy +] = tableSetAccessPolicyOperationSpec; +Specifications[ + Operation.Service_SetProperties +] = serviceSetPropertiesOperationSpec; +Specifications[ + Operation.Service_GetProperties +] = serviceGetPropertiesOperationSpec; +Specifications[ + Operation.Service_GetStatistics +] = serviceGetStatisticsOperationSpec; export default Specifications; diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 653a5d0da..744fbfbb8 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -13,9 +13,10 @@ import { FULL_METADATA_ACCEPT, MINIMAL_METADATA_ACCEPT, NO_METADATA_ACCEPT, + QUERY_RESULT_MAX_NUM, RETURN_CONTENT, RETURN_NO_CONTENT, - TABLE_API_VERSION, + TABLE_API_VERSION } from "../utils/constants"; import BaseHandler from "./BaseHandler"; @@ -234,32 +235,46 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableQueryEntitiesOptionalParams, context: Context ): Promise { - // e.g - // const tableCtx = new TableStorageContext(context); - // const accountName = tableCtx.account; - // const tableName = tableCtx.tableName; // Get tableName from context - // return { - // statusCode: 200, - // date: tableCtx.startTime, - // clientRequestId: "clientRequestId", - // requestId: "requestId", - // version: "version", - // xMsContinuationNextPartitionKey: "xMsContinuationNextPartitionKey", - // xMsContinuationNextRowKey: "xMsContinuationNextRowKey", - // odatametadata: "odatametadata", - // value: [ - // { - // property1: "property1" + accountName, - // property2: "property2" + tableName, - // property3: "property3" - // }, - // { - // property1: "property1" - // } - // ] - // }; - // TODO - throw new NotImplementedError(); + const tableCtx = new TableStorageContext(context); + const tableName = tableCtx.tableName; + const accountName = tableCtx.account; + + const result = await this.metadataStore.queryTableEntities( + context, + accountName!, + tableName!, + options.queryOptions! + ); + + const response: Models.TableQueryEntitiesResponse = { + clientRequestId: options.requestId, + requestId: tableCtx.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode: 200 + }; + + const responseBody = this.getResponseBodyFromQueryResultBasedOnAccept( + tableCtx.accept!, + accountName!, + tableCtx, + result + ); + + // Set query result + response.value = responseBody.value; + if (responseBody["odata.metadata"] !== undefined) { + response.odatametadata = responseBody["odata.metadata"]; + } + + // Set x-ms-continuation-NextPartitionKey and x-ms-continuation-NextRowKey + if (result.length > QUERY_RESULT_MAX_NUM) { + response.xMsContinuationNextPartitionKey = + result[QUERY_RESULT_MAX_NUM].PartitionKey; + response.xMsContinuationNextRowKey = result[QUERY_RESULT_MAX_NUM].RowKey; + } + + return response; } public async queryEntitiesWithPartitionAndRowKey( @@ -326,13 +341,24 @@ export default class TableHandler extends BaseHandler implements ITableHandler { if (ifMatch === "") { throw StorageErrorFactory.getPreconditionFailed(context); } + + const metadata = `${accountName}/$metadata#Tables/@Element`; + const type = `${accountName}.Tables`; + const id = `Tables(${tableName})`; + const editLink = `Tables(${tableName})`; + const updateEtag = newEtag(); + // Entity, which is used to update an existing entity const entity: IEntity = { PartitionKey: options.tableEntityProperties.PartitionKey, RowKey: options.tableEntityProperties.RowKey, properties: options.tableEntityProperties, lastModifiedTime: context.startTime!, + odataMetadata: metadata, + odataType: type, + odataId: id, + odataEditLink: editLink eTag: updateEtag }; @@ -534,28 +560,26 @@ export default class TableHandler extends BaseHandler implements ITableHandler { throw StorageErrorFactory.getPropertiesNeedValue(context); } + const metadata = `${accountName}/$metadata#Tables/@Element`; + const type = `${accountName}.${tableName}`; + const id = + `${tableName}` + + `(PartitionKey='${options.tableEntityProperties.PartitionKey}',` + + `RowKey='${options.tableEntityProperties.RowKey}')`; + const editLink = id; + const entity: IEntity = { PartitionKey: options.tableEntityProperties.PartitionKey, RowKey: options.tableEntityProperties.RowKey, properties: options.tableEntityProperties, lastModifiedTime: context.startTime!, - eTag: newEtag() + eTag: newEtag(), + odataMetadata: metadata, // Here we store value without protocol and host + odataType: type, + odataId: id, + odataEditLink: editLink }; - // TODO: Move logic to get host into utility methods - let protocol = "http"; - let host = - DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; - if (tableCtx.request !== undefined) { - host = tableCtx.request.getHeader("host") as string; - protocol = tableCtx.request.getProtocol() as string; - } - - const metadata = `${protocol}://${host}/${accountName}/$metadata#Tables/@Element`; - const type = `${accountName}.Tables`; - const id = `${protocol}://${host}/Tables(${tableName})`; - const editLink = `Tables(${tableName})`; - await this.metadataStore.insertTableEntity( context, tableName, @@ -594,14 +618,22 @@ export default class TableHandler extends BaseHandler implements ITableHandler { response.statusCode = 201; response.preferenceApplied = "return-content"; + let protocol = "http"; + let host = + DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; + if (tableCtx.request !== undefined) { + host = tableCtx.request.getHeader("host") as string; + protocol = tableCtx.request.getProtocol() as string; + } + if (accept === MINIMAL_METADATA_ACCEPT) { - body["odata.metadata"] = metadata; + body["odata.metadata"] = `${protocol}://${host}/` + metadata; } if (accept === FULL_METADATA_ACCEPT) { - body["odata.metadata"] = metadata; + body["odata.metadata"] = `${protocol}://${host}/` + metadata; body["odata.type"] = type; - body["body.id"] = id; + body["body.id"] = `${protocol}://${host}/` + id; body["odata.etag"] = entity.eTag; body["odata.editLink"] = editLink; } @@ -640,4 +672,116 @@ export default class TableHandler extends BaseHandler implements ITableHandler { // TODO throw new NotImplementedError(); } + + private getResponseBodyFromQueryResultBasedOnAccept( + accept: string, + accountName: string, + tableCtx: Context, + queryResult: { [propertyName: string]: any }[] + ) { + let protocol = "http"; + let host = + DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; + + if (tableCtx.request !== undefined) { + host = tableCtx.request.getHeader("host") as string; + protocol = tableCtx.request.getProtocol() as string; + } + + const resultWithMetaData: { [propertyName: string]: any }[] = []; + const responseBody: { [propertyName: string]: any } = {}; + + switch (accept) { + case MINIMAL_METADATA_ACCEPT: { + // Add odata.metadata + (responseBody as any)["odata.metadata"] = + `${protocol}://${host}/` + queryResult[0].odataMetadata; + for (const entity of queryResult) { + const filteredEntity = {}; + for (const key of Object.keys(entity)) { + // Only need metadata and properties' odata type + if ( + key === "odataMetadata" || + key === "odataType" || + key === "odataId" || + key === "eTag" || + key === "odataEditLink" + ) { + continue; + } + // Also add odataType to each field + (filteredEntity as any)[key] = entity[key]; + } + + resultWithMetaData.push(filteredEntity); + } + (responseBody as any).value = resultWithMetaData; + break; + } + case FULL_METADATA_ACCEPT: { + // Add odata.metadata + (responseBody as any)["odata.metadata"] = queryResult[0].odataMetadata; + for (const entity of queryResult) { + const filteredEntity = {}; + for (const key of Object.keys(entity)) { + // Remove odataMetadata of each entity + if (key === "odataMetadata") { + continue; + } + (filteredEntity as any)[key] = entity[key]; + } + + // Add Timestamp@odata.type + (filteredEntity as any)["Timestamp@odata.type"] = "Edm.DateTime"; + + // Solve the name inconsistency of the response and entity + (filteredEntity as any)[ + "odata.type" + ] = (filteredEntity as any).odataType; + delete (filteredEntity as any).odataType; + + (filteredEntity as any)["odata.id"] = + `${protocol}://${host}/` + (filteredEntity as any).odataId; + delete (filteredEntity as any).odataId; + + (filteredEntity as any)["odata.etag"] = (filteredEntity as any).eTag; + delete (filteredEntity as any).eTag; + + (filteredEntity as any)[ + "odata.editLink" + ] = (filteredEntity as any).odataEditLink; + delete (filteredEntity as any).odataEditLink; + + // Add processed entity back + resultWithMetaData.push(filteredEntity); + } + (responseBody as any).value = resultWithMetaData; + break; + } + default: { + for (const entity of queryResult) { + const filteredEntity = {}; + for (const key of Object.keys(entity)) { + // Don't need metadata and properties' odata type + if ( + key === "odataMetadata" || + key === "odataType" || + key === "odataId" || + key === "eTag" || + key === "odataEditLink" || + key.indexOf("@odata.type") > 0 + ) { + continue; + } + (filteredEntity as any)[key] = entity[key]; + } + + resultWithMetaData.push(filteredEntity); + } + (responseBody as any).value = resultWithMetaData; + break; + } + } + return responseBody; + } } diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index 29f84d170..481ed5f0a 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -120,6 +120,12 @@ export function tableStorageContextMiddleware( thridQuoteIndex + 1, fourthQuoteIndex ); + } else if ( + tableSection.includes("(") && + tableSection.includes(")") && + tableSection.indexOf(")") - tableSection.indexOf("(") === 1 + ) { + tableContext.tableName = tableSection.substr(0, tableSection.indexOf("(")); } else { logger.error( `tableStorageContextMiddleware: Cannot extract table name from URL path=${req.path}`, diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index 3a5cd3b12..daece2058 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -20,6 +20,10 @@ export interface IEntity { properties: { [propertyName: string]: string | number; }; + odataMetadata: string; + odataType: string; + odataId: string; + odataEditLink: string; } export type TableModel = ITtableAdditionalProperties; @@ -37,8 +41,9 @@ export default interface ITableMetadataStore { ): Promise; queryTableEntities( context: Context, + accountName: string, table: string, - propertyName: Array + queryOptions: Models.QueryOptions ): Promise<{ [propertyName: string]: any }[]>; queryTableEntitiesWithPartitionAndRowKey( context: Context, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index 732f8d78b..d47d83f7b 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -6,6 +6,7 @@ import StorageErrorFactory from "../errors/StorageErrorFactory"; import * as Models from "../generated/artifacts/models"; import Context from "../generated/Context"; import { IEntity, TableModel } from "../persistence/ITableMetadataStore"; +import { SUPPORTED_QUERY_OPERATOR } from "../utils/constants"; import ITableMetadataStore from "./ITableMetadataStore"; export default class LokiTableMetadataStore implements ITableMetadataStore { @@ -144,11 +145,109 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { public async queryTableEntities( context: Context, - table: string, - propertyName: Array + accountName: string, + tableName: string, + queryOptions: Models.QueryOptions ): Promise<{ [propertyName: string]: any }[]> { - // TODO - throw new NotImplementedError(); + const tableColl = this.db.getCollection( + this.getUniqueTableCollectionName(accountName, tableName) + ); + + // Split parameters for filter + const filters = queryOptions.filter!.split("and"); + const filterJson = {}; + for (let condition of filters) { + condition = condition.trim(); + const length = condition.length; + + // Remove wrapping parentheses + if (condition[0] === "(" && condition[length - 1] === ")") { + condition = condition.substr(1, length - 2); + } + + const comps = condition.split(" "); + if (comps.length !== 3) { + throw StorageErrorFactory.getQueryConditionInvalid(context); + } + + let operator = comps[1]; + const firstParam = "properties." + comps[0]; + let secondParam = comps[2]; + + if (SUPPORTED_QUERY_OPERATOR.indexOf(operator) >= 0) { + const rightExpressionJSON = {}; + + // Fix inconsistency with azure table query operator + // and lokijs query operator + if (operator === "ge") { + operator = "gte"; + } + + if (operator === "le") { + operator = "lte"; + } + + operator = "$" + operator; + secondParam = this.convertQueryParameters(secondParam, context); + + (rightExpressionJSON as any)[operator] = secondParam; + (filterJson as any)[firstParam] = rightExpressionJSON; + } else { + throw StorageErrorFactory.getQueryConditionInvalid(context); + } + } + + // Query Result + const result = tableColl.find(filterJson); + if (result.length === 0) { + return result; + } + + let selectedResult = result; + + // Only return selected fields + if (queryOptions.select !== undefined) { + const selectedFieldsResult = []; + const selectedFields = queryOptions.select.split(","); + + // Iterate all entities and get selected fields + for (const entity of result) { + // Check if the selected result has exceeded the top limits + const entitySelectedFieldResult = {}; + (entitySelectedFieldResult as any).PartitionKey = entity.PartitionKey; + (entitySelectedFieldResult as any).RowKey = entity.RowKey; + (entitySelectedFieldResult as any).odataMetadata = entity.odataMetadata; + (entitySelectedFieldResult as any).odataType = entity.odataType; + (entitySelectedFieldResult as any).odataId = entity.odataId; + (entitySelectedFieldResult as any).odataEditLink = entity.odataEditLink; + (entitySelectedFieldResult as any).eTag = entity.eTag; + (entitySelectedFieldResult as any).Timestamp = entity.lastModifiedTime; + + for (let field of selectedFields) { + field = field.trim(); + const keys = field.split("."); + let val = entity.properties; + for (const key of keys) { + val = val[key]; + } + (entitySelectedFieldResult as any)[field] = val; + (entitySelectedFieldResult as any)[ + field + "@odata.type" + ] = this.getODataType(val); + } + + // Add to result + selectedFieldsResult.push(entitySelectedFieldResult); + } + + selectedResult = selectedFieldsResult; + } + + if (queryOptions.top !== undefined) { + selectedResult = selectedResult.slice(0, queryOptions.top!); + } + + return selectedResult; } public async queryTableEntitiesWithPartitionAndRowKey( @@ -365,4 +464,57 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { ): string { return `${accountName}$${tableName}`; } + + private convertQueryParameters(param: string, context: Context): any { + const length = param.length; + if (param[0] === "'" && param[length - 1] === "'") { + // Param is of type string + // Convert middle '' to ' + const idx = param.indexOf("''"); + if (idx > 0) { + param = param.substr(0, idx) + param.substr(idx + 1, length); + } + return param.substr(1, param.length - 2); + } + + if (param === "true" || param === "false") { + // Param is of type boolean + return param === "true"; + } + + const floatVal = parseFloat(param); + const intVal = parseInt(param, 10); + + if (!isNaN(floatVal)) { + if (intVal === floatVal) { + return intVal; + } else { + return floatVal; + } + } else { + throw StorageErrorFactory.getQueryConditionInvalid(context); + } + } + + private getODataType(val: any) { + switch (typeof val) { + case "string": { + return "Edm.String"; + } + case "number": { + if (Number.isInteger(val)) { + return "Edm.Int32"; + } else { + return "Edm.Float"; + } + } + case "boolean": { + return "Edm.Boolean"; + } + } + + if (val instanceof Date) { + return "Edm.DateTime"; + } + } } diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index 234313a9b..26226f95c 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -28,6 +28,8 @@ export const HeaderConstants = { X_MS_VERSION: "x-ms-version" }; +export const SUPPORTED_QUERY_OPERATOR = ["eq", "gt", "ge", "lt", "le", "ne"]; + export const NO_METADATA_ACCEPT = "application/json;odata=nometadata"; export const MINIMAL_METADATA_ACCEPT = "application/json;odata=minimalmetadata"; export const FULL_METADATA_ACCEPT = "application/json;odata=fullmetadata"; @@ -35,6 +37,7 @@ export const FULL_METADATA_ACCEPT = "application/json;odata=fullmetadata"; export const RETURN_NO_CONTENT = "return-no-content"; export const RETURN_CONTENT = "return-content"; +export const QUERY_RESULT_MAX_NUM = 0; export const ValidAPIVersions = [ "2019-12-12", "2019-07-07", From 2a77382beb7c43e9d5d7e6695da1e955233032c9 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Tue, 10 Nov 2020 16:54:18 +0800 Subject: [PATCH 20/57] Table Phase-1 refactor (#608) * Ignore tslint check for generated code * Refactor table interfaces * Workaround: Change query entity with ParitionKey and RowKey response to file * Refactoring section 2 * Added query entity with pk & rk * Add support for different types of query entity * Query entity work without select and filter * Add Edm types * Update query entities response to stream * Fixed issues with .Net SDK * Allow null property; Ingore update/merge paritionkey and rowkey in body * Azurite V2 filter * Merge entity will not keep existing entity type * Update TS version; Support query entities select * Add support for query table nextTable * Fixed issues found during testing with track2 net table SDK * Disable debuglog in table test --- package-lock.json | 73 +- package.json | 6 +- src/blob/persistence/LokiBlobMetadataStore.ts | 38 +- .../persistence/SqlExtentMetadataStore.ts | 11 +- src/table/TableRequestListenerFactory.ts | 8 +- .../TableSharedKeyAuthenticator.ts | 14 +- .../TableSharedKeyLiteAuthenticator.ts | 194 +++ src/table/entity/EdmBinary.ts | 64 + src/table/entity/EdmBoolean.ts | 42 + src/table/entity/EdmDateTime.ts | 63 + src/table/entity/EdmDouble.ts | 83 ++ src/table/entity/EdmGuid.ts | 64 + src/table/entity/EdmInt32.ts | 44 + src/table/entity/EdmInt64.ts | 64 + src/table/entity/EdmNull.ts | 40 + src/table/entity/EdmString.ts | 46 + src/table/entity/EntityProperty.ts | 214 +++ src/table/entity/IEdmType.ts | 56 + src/table/entity/NormalizedEntity.ts | 101 ++ src/table/errors/StorageError.ts | 11 +- src/table/errors/StorageErrorFactory.ts | 41 +- src/table/generated/artifacts/models.ts | 14 +- .../generated/artifacts/specifications.ts | 199 ++- src/table/handlers/TableHandler.ts | 1221 +++++++++-------- .../tableStorageContext.middleware.ts | 22 +- src/table/persistence/ITableMetadataStore.ts | 86 +- .../persistence/LokiTableMetadataStore.ts | 948 ++++++++----- src/table/utils/constants.ts | 8 +- src/table/utils/utils.ts | 221 ++- swagger/table.md | 30 +- tests/table/apis/table.test.ts | 45 +- tests/testutils.ts | 32 +- tslint.json | 8 +- 33 files changed, 2971 insertions(+), 1140 deletions(-) create mode 100644 src/table/authentication/TableSharedKeyLiteAuthenticator.ts create mode 100644 src/table/entity/EdmBinary.ts create mode 100644 src/table/entity/EdmBoolean.ts create mode 100644 src/table/entity/EdmDateTime.ts create mode 100644 src/table/entity/EdmDouble.ts create mode 100644 src/table/entity/EdmGuid.ts create mode 100644 src/table/entity/EdmInt32.ts create mode 100644 src/table/entity/EdmInt64.ts create mode 100644 src/table/entity/EdmNull.ts create mode 100644 src/table/entity/EdmString.ts create mode 100644 src/table/entity/EntityProperty.ts create mode 100644 src/table/entity/IEdmType.ts create mode 100644 src/table/entity/NormalizedEntity.ts diff --git a/package-lock.json b/package-lock.json index 0574691a0..15dd1eb0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -534,6 +534,12 @@ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1705,17 +1711,17 @@ } }, "bl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", - "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.1.tgz", + "integrity": "sha512-jrCW5ZhfQ/Vt07WX1Ngs+yn9BDqPL/gw28S7s9H6QK/gupnizNzJAss5akW20ISgOrbLTlXOOCTJeNUQqruAWQ==", "requires": { "readable-stream": "^3.0.1" }, "dependencies": { "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -4218,9 +4224,9 @@ } }, "make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "map-age-cleaner": { @@ -5050,9 +5056,9 @@ "dev": true }, "prettier": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", - "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==", "dev": true }, "prettier-tslint": { @@ -6173,25 +6179,22 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "ts-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", "dev": true, "requires": { - "arrify": "^1.0.0", - "buffer-from": "^1.1.0", - "diff": "^3.1.0", + "arg": "^4.1.0", + "diff": "^4.0.1", "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.6", - "yn": "^2.0.0" + "source-map-support": "^0.5.17", + "yn": "3.1.1" }, "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, "source-map": { @@ -6201,9 +6204,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -6312,9 +6315,9 @@ } }, "typescript": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz", - "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", "dev": true }, "uc.micro": { @@ -6790,9 +6793,9 @@ } }, "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true }, "yup": { diff --git a/package.json b/package.json index 3c6c9129a..12ff8fded 100644 --- a/package.json +++ b/package.json @@ -66,11 +66,11 @@ "husky": "^1.3.1", "lint-staged": "^8.1.5", "mocha": "^5.2.0", - "prettier": "^1.16.4", + "prettier": "^2.1.2", "prettier-tslint": "^0.4.2", - "ts-node": "^7.0.1", + "ts-node": "^9.0.0", "tslint": "^5.20.1", - "typescript": "^3.1.4", + "typescript": "^4.0.5", "vsce": "^1.64.0" }, "activationEvents": [ diff --git a/src/blob/persistence/LokiBlobMetadataStore.ts b/src/blob/persistence/LokiBlobMetadataStore.ts index 9dbbaec85..fa75da012 100644 --- a/src/blob/persistence/LokiBlobMetadataStore.ts +++ b/src/blob/persistence/LokiBlobMetadataStore.ts @@ -121,7 +121,7 @@ export default class LokiBlobMetadataStore await new Promise((resolve, reject) => { stat(this.lokiDBPath, (statError, stats) => { if (!statError) { - this.db.loadDatabase({}, dbError => { + this.db.loadDatabase({}, (dbError) => { if (dbError) { reject(dbError); } else { @@ -169,7 +169,7 @@ export default class LokiBlobMetadataStore } await new Promise((resolve, reject) => { - this.db.saveDatabase(err => { + this.db.saveDatabase((err) => { if (err) { reject(err); } else { @@ -190,7 +190,7 @@ export default class LokiBlobMetadataStore */ public async close(): Promise { await new Promise((resolve, reject) => { - this.db.close(err => { + this.db.close((err) => { if (err) { reject(err); } else { @@ -331,13 +331,13 @@ export default class LokiBlobMetadataStore .chain() .find(query) .find(query2) - .limit(maxResults + 1) .simplesort("name") + .limit(maxResults + 1) .data(); if (docs.length <= maxResults) { return [ - docs.map(doc => { + docs.map((doc) => { return LeaseFactory.createLeaseState( new ContainerLeaseAdapter(doc), context @@ -350,7 +350,7 @@ export default class LokiBlobMetadataStore const nextMarker = docs[docs.length - 2].name; docs.pop(); return [ - docs.map(doc => { + docs.map((doc) => { return LeaseFactory.createLeaseState( new ContainerLeaseAdapter(doc), context @@ -845,13 +845,13 @@ export default class LokiBlobMetadataStore const docs = await coll .chain() .find(query) - .where(obj => { + .where((obj) => { return obj.name > marker!; }) - .where(obj => { + .where((obj) => { return includeSnapshots ? true : obj.snapshot.length === 0; }) - .where(obj => { + .where((obj) => { return includeUncommittedBlobs ? true : obj.isCommitted; }) .simplesort("name") @@ -867,7 +867,7 @@ export default class LokiBlobMetadataStore if (docs.length <= maxResults) { return [ - docs.map(doc => { + docs.map((doc) => { return LeaseFactory.createLeaseState( new BlobLeaseAdapter(doc), context @@ -879,7 +879,7 @@ export default class LokiBlobMetadataStore const nextMarker = docs[docs.length - 2].name; docs.pop(); return [ - docs.map(doc => { + docs.map((doc) => { return LeaseFactory.createLeaseState( new BlobLeaseAdapter(doc), context @@ -900,13 +900,13 @@ export default class LokiBlobMetadataStore const docs = await coll .chain() - .where(obj => { + .where((obj) => { return obj.name > marker!; }) - .where(obj => { + .where((obj) => { return includeSnapshots ? true : obj.snapshot.length === 0; }) - .where(obj => { + .where((obj) => { return includeUncommittedBlobs ? true : obj.isCommitted; }) .simplesort("name") @@ -2310,7 +2310,7 @@ export default class LokiBlobMetadataStore doc.properties.contentLanguage = blob.properties.contentLanguage; doc.properties.contentDisposition = blob.properties.contentDisposition; doc.properties.contentLength = selectedBlockList - .map(block => block.size) + .map((block) => block.size) .reduce((total, val) => { return total + val; }, 0); @@ -2324,7 +2324,7 @@ export default class LokiBlobMetadataStore } else { blob.committedBlocksInOrder = selectedBlockList; blob.properties.contentLength = selectedBlockList - .map(block => block.size) + .map((block) => block.size) .reduce((total, val) => { return total + val; }, 0); @@ -2782,7 +2782,7 @@ export default class LokiBlobMetadataStore const coll = this.db.getCollection(this.BLOCKS_COLLECTION); const blockDocs = coll .chain() - .where(obj => { + .where((obj) => { return obj.$loki > parseInt(marker, 10); }) .simplesort("$loki") @@ -2790,11 +2790,11 @@ export default class LokiBlobMetadataStore .data(); if (blockDocs.length <= maxResults) { - return [blockDocs.map(block => block.persistency), undefined]; + return [blockDocs.map((block) => block.persistency), undefined]; } else { blockDocs.pop(); const nextMarker = `${blockDocs[maxResults - 1].$loki}`; - return [blockDocs.map(block => block.persistency), nextMarker]; + return [blockDocs.map((block) => block.persistency), nextMarker]; } } diff --git a/src/common/persistence/SqlExtentMetadataStore.ts b/src/common/persistence/SqlExtentMetadataStore.ts index a3f3e4dfe..b15691f4e 100644 --- a/src/common/persistence/SqlExtentMetadataStore.ts +++ b/src/common/persistence/SqlExtentMetadataStore.ts @@ -106,13 +106,12 @@ export default class SqlExtentMetadataStore implements IExtentMetadataStore { */ public async updateExtent(extent: IExtentModel): Promise { return ExtentsModel.upsert({ - id: extent.id, ...extent }) .then(() => { return; }) - .catch(err => { + .catch((err) => { // console.log(`SqlExtentMetadataStore.updateExtent() upsert err:${err}`); throw err; }); @@ -181,13 +180,13 @@ export default class SqlExtentMetadataStore implements IExtentMetadataStore { limit: maxResults, where: query as any, order: [["id", "ASC"]] - }).then(res => { + }).then((res) => { if (res.length < maxResults!) { - return [res.map(val => modelConvert(val)), undefined]; + return [res.map((val) => modelConvert(val)), undefined]; } else { const tailItem = res[res.length - 1]; const nextMarker = this.getModelValue(tailItem, "id", true); - return [res.map(val => modelConvert(val)), nextMarker]; + return [res.map((val) => modelConvert(val)), nextMarker]; } }); } @@ -221,7 +220,7 @@ export default class SqlExtentMetadataStore implements IExtentMetadataStore { where: { id: extentId } - }).then(res => { + }).then((res) => { if (res === null || res === undefined) { throw Error( `SqlExtentMetadataStore:getExtentLocationId() Error. Extent not exists.` diff --git a/src/table/TableRequestListenerFactory.ts b/src/table/TableRequestListenerFactory.ts index 9497a113b..0e7c4c340 100644 --- a/src/table/TableRequestListenerFactory.ts +++ b/src/table/TableRequestListenerFactory.ts @@ -7,6 +7,7 @@ import logger from "../common/Logger"; import AccountSASAuthenticator from "./authentication/AccountSASAuthenticator"; import IAuthenticator from "./authentication/IAuthenticator"; import TableSASAuthenticator from "./authentication/TableSASAuthenticator"; +import { TableQueryResponse } from "./generated/artifacts/mappers"; import { Operation } from "./generated/artifacts/operation"; import Specifications from "./generated/artifacts/specifications"; import ExpressMiddlewareFactory from "./generated/ExpressMiddlewareFactory"; @@ -21,6 +22,7 @@ import { DEFAULT_TABLE_CONTEXT_PATH } from "./utils/constants"; import morgan = require("morgan"); import TableSharedKeyAuthenticator from "./authentication/TableSharedKeyAuthenticator"; +import TableSharedKeyLiteAuthenticator from "./authentication/TableSharedKeyLiteAuthenticator"; /** * Default RequestListenerFactory based on express framework. * @@ -56,7 +58,7 @@ export default class TableRequestListenerFactory Operation.Table_MergeEntity, Operation.Table_DeleteEntity, Operation.Table_InsertEntity - ].forEach(operation => { + ].forEach((operation) => { (Specifications[operation] as MutableSpecification).isXML = false; }); @@ -71,6 +73,9 @@ export default class TableRequestListenerFactory } ); + // TODO: Override Query Table JSON response element value + TableQueryResponse.type.modelProperties!.value.xmlElementName = "value"; + const app = express().disable("x-powered-by"); // MiddlewareFactory is a factory to create auto-generated middleware @@ -110,6 +115,7 @@ export default class TableRequestListenerFactory logger ); const authenticators: IAuthenticator[] = [ + new TableSharedKeyLiteAuthenticator(this.accountDataStore, logger), new TableSharedKeyAuthenticator(this.accountDataStore, logger), new AccountSASAuthenticator(this.accountDataStore, logger), new TableSASAuthenticator( diff --git a/src/table/authentication/TableSharedKeyAuthenticator.ts b/src/table/authentication/TableSharedKeyAuthenticator.ts index 5c617c813..b7ddc7c88 100644 --- a/src/table/authentication/TableSharedKeyAuthenticator.ts +++ b/src/table/authentication/TableSharedKeyAuthenticator.ts @@ -177,12 +177,16 @@ export default class TableSharedKeyAuthenticator implements IAuthenticator { } } - queryKeys.sort(); - for (const key of queryKeys) { - canonicalizedResourceString += `\n${key}:${decodeURIComponent( - lowercaseQueries[key] - )}`; + if (queryKeys.includes("comp")) { + canonicalizedResourceString += "?comp=" + lowercaseQueries.comp; } + + // queryKeys.sort(); + // for (const key of queryKeys) { + // canonicalizedResourceString += `\n${key}:${decodeURIComponent( + // lowercaseQueries[key] + // )}`; + // } } return canonicalizedResourceString; diff --git a/src/table/authentication/TableSharedKeyLiteAuthenticator.ts b/src/table/authentication/TableSharedKeyLiteAuthenticator.ts new file mode 100644 index 000000000..5cf411471 --- /dev/null +++ b/src/table/authentication/TableSharedKeyLiteAuthenticator.ts @@ -0,0 +1,194 @@ +import IAccountDataStore from "../../common/IAccountDataStore"; +import ILogger from "../../common/ILogger"; +import { computeHMACSHA256, getURLQueries } from "../../common/utils/utils"; +import TableStorageContext from "../context/TableStorageContext"; +import StorageErrorFactory from "../errors/StorageErrorFactory"; +import Context from "../generated/Context"; +import IRequest from "../generated/IRequest"; +import { HeaderConstants } from "../utils/constants"; +import IAuthenticator from "./IAuthenticator"; + +export default class TableSharedKeyLiteAuthenticator implements IAuthenticator { + public constructor( + private readonly dataStore: IAccountDataStore, + private readonly logger: ILogger + ) {} + + public async validate( + req: IRequest, + context: Context + ): Promise { + const tableContext = new TableStorageContext(context); + const account = tableContext.account!; + + this.logger.info( + `TableSharedKeyLiteAuthenticator:validate() Start validation against account shared key authentication.`, + tableContext.contextID + ); + + const authHeaderValue = req.getHeader(HeaderConstants.AUTHORIZATION); + if ( + authHeaderValue === undefined || + !authHeaderValue.startsWith("SharedKeyLite") + ) { + this.logger.info( + // tslint:disable-next-line:max-line-length + `TableSharedKeyLiteAuthenticator:validate() Request doesn't include valid authentication header. Skip SharedKeyLite authentication.`, + tableContext.contextID + ); + return; + } + + // TODO: Make following async + const accountProperties = this.dataStore.getAccount(account); + if (accountProperties === undefined) { + this.logger.error( + `TableSharedKeyLiteAuthenticator:validate() Invalid storage account ${account}.`, + tableContext.contextID + ); + throw StorageErrorFactory.getInvalidOperation( + tableContext.contextID!, + "Invalid storage account." + ); + } + + const stringToSign: string = + [ + this.getHeaderValueToSign(req, HeaderConstants.DATE) || + this.getHeaderValueToSign(req, HeaderConstants.X_MS_DATE) + ].join("\n") + + "\n" + + this.getCanonicalizedResourceString( + req, + account, + tableContext.authenticationPath + ); + + this.logger.info( + `TableSharedKeyLiteAuthenticator:validate() [STRING TO SIGN]:${JSON.stringify( + stringToSign + )}`, + tableContext.contextID + ); + + const signature1 = computeHMACSHA256(stringToSign, accountProperties.key1); + const authValue1 = `SharedKeyLite ${account}:${signature1}`; + this.logger.info( + `TableSharedKeyLiteAuthenticator:validate() Calculated authentication header based on key1: ${authValue1}`, + tableContext.contextID + ); + if (authHeaderValue === authValue1) { + this.logger.info( + `TableSharedKeyLiteAuthenticator:validate() Signature 1 matched.`, + tableContext.contextID + ); + return true; + } + + if (accountProperties.key2) { + const signature2 = computeHMACSHA256( + stringToSign, + accountProperties.key2 + ); + const authValue2 = `SharedKeyLite ${account}:${signature2}`; + this.logger.info( + `TableSharedKeyLiteAuthenticator:validate() Calculated authentication header based on key2: ${authValue2}`, + tableContext.contextID + ); + if (authHeaderValue === authValue2) { + this.logger.info( + `TableSharedKeyLiteAuthenticator:validate() Signature 2 matched.`, + tableContext.contextID + ); + return true; + } + } + + // this.logger.info(`[URL]:${req.getUrl()}`); + // this.logger.info(`[HEADERS]:${req.getHeaders().toString()}`); + // this.logger.info(`[KEY]: ${request.headers.get(HeaderConstants.AUTHORIZATION)}`); + + this.logger.info( + `TableSharedKeyLiteAuthenticator:validate() Validation failed.`, + tableContext.contextID + ); + return false; + } + + /** + * Retrieve header value according to shared key sign rules. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + * + * @private + * @param {WebResource} request + * @param {string} headerName + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ + private getHeaderValueToSign(request: IRequest, headerName: string): string { + const value = request.getHeader(headerName); + + if (!value) { + return ""; + } + + // When using version 2015-02-21 or later, if Content-Length is zero, then + // set the Content-Length part of the StringToSign to an empty string. + // https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + if (headerName === HeaderConstants.CONTENT_LENGTH && value === "0") { + return ""; + } + + return value; + } + + /** + * Retrieves canonicalized resource string. + * + * @private + * @param {IRequest} request + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ + private getCanonicalizedResourceString( + request: IRequest, + account: string, + authenticationPath?: string + ): string { + let path = request.getPath() || "/"; + + // For secondary account, we use account name (without "-secondary") for the path + if (authenticationPath !== undefined) { + path = authenticationPath; + } + + let canonicalizedResourceString: string = ""; + canonicalizedResourceString += `/${account}${path}`; + + const queries = getURLQueries(request.getUrl()); + const lowercaseQueries: { [key: string]: string } = {}; + if (queries) { + const queryKeys: string[] = []; + for (const key in queries) { + if (queries.hasOwnProperty(key)) { + const lowercaseKey = key.toLowerCase(); + lowercaseQueries[lowercaseKey] = queries[key]; + queryKeys.push(lowercaseKey); + } + } + + if (queryKeys.includes("comp")) { + canonicalizedResourceString += "?comp=" + lowercaseQueries.comp; + } + + // queryKeys.sort(); + // for (const key of queryKeys) { + // canonicalizedResourceString += `\n${key}:${decodeURIComponent( + // lowercaseQueries[key] + // )}`; + // } + } + + return canonicalizedResourceString; + } +} diff --git a/src/table/entity/EdmBinary.ts b/src/table/entity/EdmBinary.ts new file mode 100644 index 000000000..b0a1f923f --- /dev/null +++ b/src/table/entity/EdmBinary.ts @@ -0,0 +1,64 @@ +import { ODATA_TYPE } from "../utils/constants"; +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmBinary implements IEdmType { + public static validate(value: any): string { + if (typeof value !== "string") { + throw TypeError(`Not a valid EdmBinary string.`); + } + + // TODO: Check base64 + + return value; + } + + public typedValue: string; + + public constructor(public value: any) { + this.typedValue = EdmBinary.validate(value); + } + + public toJsonPropertyValuePair(name: string): [string, string] { + return [name, this.value]; + } + + public toJsonPropertyValueString(name: string): string { + return `"${name}":"${this.value}"`; + } + + public toJsonPropertyTypePair( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): [string, string] | undefined { + if (isSystemProperty) { + throw RangeError(`EdmBinary type shouldn't be a system property.`); + } + + if ( + annotationLevel === AnnotationLevel.MINIMAL || + annotationLevel === AnnotationLevel.FULL + ) { + return [`${name}${ODATA_TYPE}`, "Edm.Binary"]; + } + } + + public toJsonPropertyTypeString( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): string | undefined { + const res = this.toJsonPropertyTypePair( + name, + annotationLevel, + isSystemProperty + ); + if (!res) { + return; + } + + const [key, value] = res; + return `"${key}":"${value}"`; + } +} diff --git a/src/table/entity/EdmBoolean.ts b/src/table/entity/EdmBoolean.ts new file mode 100644 index 000000000..a5c6cd9c9 --- /dev/null +++ b/src/table/entity/EdmBoolean.ts @@ -0,0 +1,42 @@ +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmBoolean implements IEdmType { + public static validate(value: any): boolean { + if (typeof value !== "boolean") { + throw TypeError(`Not a valid EdmBoolean string.`); + } + + return value; + } + + public typedValue: boolean; + + public constructor(public value: any) { + this.typedValue = EdmBoolean.validate(value); + } + + public toJsonPropertyValuePair(name: string): [string, boolean] { + return [name, this.typedValue]; + } + + public toJsonPropertyValueString(name: string): string { + return `"${name}":${this.value}`; + } + + public toJsonPropertyTypePair( + _name: string, + _annotationLevel: AnnotationLevel, + _isSystemProperty: boolean + ): [string, string] | undefined { + return; + } + + public toJsonPropertyTypeString( + _name: string, + _annotationLevel: AnnotationLevel, + _isSystemProperty: boolean + ): string | undefined { + return; + } +} diff --git a/src/table/entity/EdmDateTime.ts b/src/table/entity/EdmDateTime.ts new file mode 100644 index 000000000..51efc1732 --- /dev/null +++ b/src/table/entity/EdmDateTime.ts @@ -0,0 +1,63 @@ +import { ODATA_TYPE } from "../utils/constants"; +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmDateTime implements IEdmType { + public static validate(value: any): string { + if (typeof value !== "string") { + throw TypeError(`Not a valid EdmDateTime string.`); + } + + // TODO: Check data time string format + + return value; + } + + public typedValue: string; + + public constructor(public value: any) { + this.typedValue = EdmDateTime.validate(value); + } + + public toJsonPropertyValuePair(name: string): [string, string] { + return [name, this.value]; + } + + public toJsonPropertyValueString(name: string): string { + return `"${name}":"${this.value}"`; + } + + public toJsonPropertyTypePair( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): [string, string] | undefined { + if ( + annotationLevel === AnnotationLevel.MINIMAL || + annotationLevel === AnnotationLevel.FULL + ) { + if (annotationLevel === AnnotationLevel.MINIMAL && isSystemProperty) { + return; + } + return [`${name}${ODATA_TYPE}`, "Edm.DateTime"]; + } + } + + public toJsonPropertyTypeString( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): string | undefined { + const res = this.toJsonPropertyTypePair( + name, + annotationLevel, + isSystemProperty + ); + if (!res) { + return; + } + + const [key, value] = res; + return `"${key}":"${value}"`; + } +} diff --git a/src/table/entity/EdmDouble.ts b/src/table/entity/EdmDouble.ts new file mode 100644 index 000000000..2f9c1f571 --- /dev/null +++ b/src/table/entity/EdmDouble.ts @@ -0,0 +1,83 @@ +import { ODATA_TYPE } from "../utils/constants"; +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmDouble implements IEdmType { + public static validate(value: any): number | string { + if (value === "NaN" || value === "Infinity" || value === "-Infinity") { + return value; + } + + if (typeof value === "string") { + // TODO: Support convert from string. parseFloat doesn't strictly checks non number chars + const val = Number.parseFloat(value); + if (!Number.isNaN(val)) { + return val; + } + } + + if (typeof value !== "number") { + throw TypeError(`Not a valid EdmDouble string.`); + } + + return value; + } + + public typedValue: number | string; + + public constructor(public value: any) { + this.typedValue = EdmDouble.validate(value); + } + + public toJsonPropertyValuePair(name: string): [string, number] { + return [name, this.value]; + } + + public toJsonPropertyValueString(name: string): string { + if (typeof this.typedValue === "number") { + return `"${name}":${ + Number.isInteger(this.value) ? this.typedValue.toFixed(1) : this.value + }`; + } else { + return `"${name}":"${this.value}"`; + } + } + + public toJsonPropertyTypePair( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean, + force: boolean = false + ): [string, string] | undefined { + if (isSystemProperty) { + throw RangeError(`EdmDouble type shouldn't be a system property.`); + } + + if ( + force || + (typeof this.typedValue === "string" && + (annotationLevel === AnnotationLevel.MINIMAL || + annotationLevel === AnnotationLevel.FULL)) + ) { + return [`${name}${ODATA_TYPE}`, "Edm.Double"]; + } + } + + public toJsonPropertyTypeString( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): string | undefined { + const res = this.toJsonPropertyTypePair( + name, + annotationLevel, + isSystemProperty + ); + if (!res) { + return; + } + + const [key, value] = res; + return `"${key}":"${value}"`; + } +} diff --git a/src/table/entity/EdmGuid.ts b/src/table/entity/EdmGuid.ts new file mode 100644 index 000000000..64cb419d1 --- /dev/null +++ b/src/table/entity/EdmGuid.ts @@ -0,0 +1,64 @@ +import { ODATA_TYPE } from "../utils/constants"; +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmGuid implements IEdmType { + public static validate(value: any): string { + if (typeof value !== "string") { + throw TypeError(`Not a valid EdmGuid string.`); + } + + // TODO: Check GUID string format + + return value; + } + + public typedValue: string; + + public constructor(public value: any) { + this.typedValue = EdmGuid.validate(value); + } + + public toJsonPropertyValuePair(name: string): [string, string] { + return [name, this.value]; + } + + public toJsonPropertyValueString(name: string): string { + return `"${name}":"${this.value}"`; + } + + public toJsonPropertyTypePair( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): [string, string] | undefined { + if (isSystemProperty) { + throw RangeError(`EdmGuid type shouldn't be a system property.`); + } + + if ( + annotationLevel === AnnotationLevel.MINIMAL || + annotationLevel === AnnotationLevel.FULL + ) { + return [`${name}${ODATA_TYPE}`, "Edm.Guid"]; + } + } + + public toJsonPropertyTypeString( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): string | undefined { + const res = this.toJsonPropertyTypePair( + name, + annotationLevel, + isSystemProperty + ); + if (!res) { + return; + } + + const [key, value] = res; + return `"${key}":"${value}"`; + } +} diff --git a/src/table/entity/EdmInt32.ts b/src/table/entity/EdmInt32.ts new file mode 100644 index 000000000..3ede1b283 --- /dev/null +++ b/src/table/entity/EdmInt32.ts @@ -0,0 +1,44 @@ +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmInt32 implements IEdmType { + public static validate(value: any): number { + if (typeof value !== "number") { + throw TypeError(`Not a valid EdmInt32 string.`); + } + + // TODO: Check not an integer + + return value; + } + + public typedValue: number; + + public constructor(public value: any) { + this.typedValue = EdmInt32.validate(value); + } + + public toJsonPropertyValuePair(name: string): [string, number] { + return [name, this.value]; + } + + public toJsonPropertyValueString(name: string): string { + return `"${name}":${this.value}`; + } + + public toJsonPropertyTypePair( + _name: string, + _annotationLevel: AnnotationLevel, + _isSystemProperty: boolean + ): [string, string] | undefined { + return; + } + + public toJsonPropertyTypeString( + _name: string, + _annotationLevel: AnnotationLevel, + _isSystemProperty: boolean + ): string | undefined { + return; + } +} diff --git a/src/table/entity/EdmInt64.ts b/src/table/entity/EdmInt64.ts new file mode 100644 index 000000000..ad925ac1d --- /dev/null +++ b/src/table/entity/EdmInt64.ts @@ -0,0 +1,64 @@ +import { ODATA_TYPE } from "../utils/constants"; +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmInt64 implements IEdmType { + public static validate(value: any): string { + if (typeof value !== "string") { + throw TypeError(`Not a valid EdmInt64 string.`); + } + + // TODO: Check base64 + + return value; + } + + public typedValue: string; + + public constructor(public value: any) { + this.typedValue = EdmInt64.validate(value); + } + + public toJsonPropertyValuePair(name: string): [string, string] { + return [name, this.value]; + } + + public toJsonPropertyValueString(name: string): string { + return `"${name}":"${this.value}"`; + } + + public toJsonPropertyTypePair( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): [string, string] | undefined { + if (isSystemProperty) { + throw RangeError(`EdmInt64 type shouldn't be a system property.`); + } + + if ( + annotationLevel === AnnotationLevel.MINIMAL || + annotationLevel === AnnotationLevel.FULL + ) { + return [`${name}${ODATA_TYPE}`, "Edm.Int64"]; + } + } + + public toJsonPropertyTypeString( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): string | undefined { + const res = this.toJsonPropertyTypePair( + name, + annotationLevel, + isSystemProperty + ); + if (!res) { + return; + } + + const [key, value] = res; + return `"${key}":"${value}"`; + } +} diff --git a/src/table/entity/EdmNull.ts b/src/table/entity/EdmNull.ts new file mode 100644 index 000000000..edf25ac61 --- /dev/null +++ b/src/table/entity/EdmNull.ts @@ -0,0 +1,40 @@ +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmNull implements IEdmType { + public static validate(value: any): void { + if (typeof value !== "object" && value !== null) { + throw TypeError(`Not a valid EdmNull string.`); + } + } + + public constructor(public value: any) { + EdmNull.validate(value); + } + + public toJsonPropertyValuePair( + name: string + ): [string, string | number | boolean] | undefined { + return; + } + + public toJsonPropertyValueString(name: string): string | undefined { + return; + } + + public toJsonPropertyTypePair( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): [string, string] | undefined { + return; + } + + public toJsonPropertyTypeString( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): string | undefined { + return; + } +} diff --git a/src/table/entity/EdmString.ts b/src/table/entity/EdmString.ts new file mode 100644 index 000000000..913da74a0 --- /dev/null +++ b/src/table/entity/EdmString.ts @@ -0,0 +1,46 @@ +import { AnnotationLevel } from "./EntityProperty"; +import { IEdmType } from "./IEdmType"; + +export class EdmString implements IEdmType { + public static validate(value: any): string { + if (typeof value !== "string") { + throw TypeError(`Not a valid string.`); + } + + // TODO: Check GUID string format + + return value; + } + + public typedValue: string; + + public constructor(public value: any) { + this.typedValue = EdmString.validate(value); + } + + public toJsonPropertyValuePair( + name: string + ): [string, string | number | boolean] { + return [name, this.value]; + } + + public toJsonPropertyValueString(name: string): string { + return `"${name}":"${this.value}"`; + } + + public toJsonPropertyTypePair( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): [string, string] | undefined { + return; + } + + public toJsonPropertyTypeString( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): string | undefined { + return; + } +} diff --git a/src/table/entity/EntityProperty.ts b/src/table/entity/EntityProperty.ts new file mode 100644 index 000000000..74c14e1a8 --- /dev/null +++ b/src/table/entity/EntityProperty.ts @@ -0,0 +1,214 @@ +import { Entity } from "../persistence/ITableMetadataStore"; +import { + FULL_METADATA_ACCEPT, + MINIMAL_METADATA_ACCEPT, + NO_METADATA_ACCEPT +} from "../utils/constants"; +import { EdmBinary } from "./EdmBinary"; +import { EdmBoolean } from "./EdmBoolean"; +import { EdmDateTime } from "./EdmDateTime"; +import { EdmDouble } from "./EdmDouble"; +import { EdmGuid } from "./EdmGuid"; +import { EdmInt32 } from "./EdmInt32"; +import { EdmInt64 } from "./EdmInt64"; +import { EdmNull } from "./EdmNull"; +import { EdmString } from "./EdmString"; +import { EdmType, getEdmType, IEdmType } from "./IEdmType"; + +export enum AnnotationLevel { + "FULL", + "MINIMAL", + "NO" +} + +export function toAnnotationLevel(level: string): AnnotationLevel { + switch (level) { + case MINIMAL_METADATA_ACCEPT: + return AnnotationLevel.MINIMAL; + case FULL_METADATA_ACCEPT: + return AnnotationLevel.FULL; + case NO_METADATA_ACCEPT: + return AnnotationLevel.NO; + default: + throw TypeError(`Invalid OData annonation level ${level}.`); + } +} + +export class EntityProperty { + public constructor( + public name: string, + public value: any, + public edmType: IEdmType, + public isSystemProperty: boolean = false + ) {} + + public toJsonPropertyValuePair(): + | [string, string | boolean | number] + | undefined { + return this.edmType.toJsonPropertyValuePair(this.name); + } + + public toJsonPropertyValueString(): string | undefined { + return this.edmType.toJsonPropertyValueString(this.name); + } + + public toJsonPropertyTypePair( + annotationLevel: AnnotationLevel + ): [string, string] | undefined { + return this.edmType.toJsonPropertyTypePair( + this.name, + annotationLevel, + this.isSystemProperty, + true + ); + } + + public toJsonPropertyTypeString( + annotationLevel: AnnotationLevel + ): string | undefined { + return this.edmType.toJsonPropertyTypeString( + this.name, + annotationLevel, + this.isSystemProperty + ); + } + + public toResponseString( + annotationLevel: AnnotationLevel | string + ): string | undefined { + const level = + typeof annotationLevel === "string" + ? toAnnotationLevel(annotationLevel) + : annotationLevel; + + const typeString = this.toJsonPropertyTypeString(level); + const propertyString = this.toJsonPropertyValueString(); + + if (typeString) { + return [typeString, propertyString].join(","); + } else { + return propertyString; + } + } + + public normalize(entity: Entity): void { + // Set back to Entity + const pair = this.toJsonPropertyValuePair(); + if (!pair) { + return; + } + + const [key, value] = pair; + entity.properties[key] = value; + + const res = this.toJsonPropertyTypePair(AnnotationLevel.FULL); + if (res) { + const [typeKey, typeValue] = res; + entity.properties[typeKey] = typeValue; + } + } +} + +export function parseEntityProperty( + name: string, + value: any, + edmType?: EdmType | string, + isSystemProperty: boolean = false +): EntityProperty { + if (edmType !== undefined) { + // Validate values per input EdmType + const type = typeof edmType === "string" ? getEdmType(edmType) : edmType; + switch (type) { + case EdmType.Binary: + // EdmBinary.validate(value); + return new EntityProperty( + name, + value, + new EdmBinary(value), + isSystemProperty + ); + case EdmType.Boolean: + // EdmBoolean.validate(value); + return new EntityProperty( + name, + value, + new EdmBoolean(value), + isSystemProperty + ); + case EdmType.DateTime: + EdmDateTime.validate(value); + return new EntityProperty( + name, + value, + new EdmDateTime(value), + isSystemProperty + ); + case EdmType.Double: + EdmDouble.validate(value); + return new EntityProperty( + name, + value, + new EdmDouble(value), + isSystemProperty + ); + case EdmType.Guid: + EdmGuid.validate(value); + return new EntityProperty( + name, + value, + new EdmGuid(value), + isSystemProperty + ); + case EdmType.Int32: + EdmInt32.validate(value); + return new EntityProperty( + name, + value, + new EdmInt32(value), + isSystemProperty + ); + case EdmType.Int64: + EdmInt64.validate(value); + return new EntityProperty( + name, + value, + new EdmInt64(value), + isSystemProperty + ); + case EdmType.String: + EdmString.validate(value); + return new EntityProperty( + name, + value, + new EdmString(value), + isSystemProperty + ); + default: + throw TypeError(`Invalid EdmType ${type}.`); + } + } else { + // Extract type from value type + switch (typeof value) { + case "string": + EdmString.validate(value); + return new EntityProperty(name, value, new EdmString(value)); + case "number": + if (Number.isInteger(value)) { + EdmInt32.validate(value); + return new EntityProperty(name, value, new EdmInt32(value)); + } else { + EdmDouble.validate(value); + return new EntityProperty(name, value, new EdmDouble(value)); + } + case "boolean": + EdmBoolean.validate(value); + return new EntityProperty(name, value, new EdmBoolean(value)); + case "object": + if (value === null) { + return new EntityProperty(name, value, new EdmNull(value)); + } + default: + throw TypeError(`Invalid value when parsing EdmType ${value}.`); + } + } +} diff --git a/src/table/entity/IEdmType.ts b/src/table/entity/IEdmType.ts new file mode 100644 index 000000000..88a0ada3d --- /dev/null +++ b/src/table/entity/IEdmType.ts @@ -0,0 +1,56 @@ +import { AnnotationLevel } from "./EntityProperty"; + +export enum EdmType { + "Binary", + "Boolean", + "DateTime", + "Double", + "Guid", + "Int32", + "Int64", + "String", + "Null" +} + +export interface IEdmType { + toJsonPropertyValuePair( + name: string + ): [string, string | number | boolean] | undefined; + toJsonPropertyValueString(name: string): string | undefined; + toJsonPropertyTypePair( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean, + force?: boolean + ): [string, string] | undefined; + toJsonPropertyTypeString( + name: string, + annotationLevel: AnnotationLevel, + isSystemProperty: boolean + ): string | undefined; +} + +export function getEdmType(type: string): EdmType { + switch (type) { + case "Edm.Binary": + return EdmType.Binary; + case "Edm.Boolean": + return EdmType.Boolean; + case "Edm.DateTime": + return EdmType.DateTime; + case "Edm.Double": + return EdmType.Double; + case "Edm.Guid": + return EdmType.Guid; + case "Edm.Int32": + return EdmType.Int32; + case "Edm.Int64": + return EdmType.Int64; + case "Edm.String": + return EdmType.String; + case "Edm.Null": + return EdmType.Null; + default: + throw TypeError(`${type} is not a valid Edm Type.`); + } +} diff --git a/src/table/entity/NormalizedEntity.ts b/src/table/entity/NormalizedEntity.ts new file mode 100644 index 000000000..e8078c177 --- /dev/null +++ b/src/table/entity/NormalizedEntity.ts @@ -0,0 +1,101 @@ +import { Entity } from "../persistence/ITableMetadataStore"; +import { ODATA_TYPE } from "../utils/constants"; +import { getTimestampString } from "../utils/utils"; +import { EdmString } from "./EdmString"; +import { EntityProperty, parseEntityProperty } from "./EntityProperty"; +// import { EdmType } from "./IEdmType"; + +export class NormalizedEntity { + public ref: Entity; + public properties: EntityProperty[] = []; + public propertiesMap: { [property: string]: EntityProperty } = {}; + + public constructor(entity: Entity) { + this.ref = entity; + + // Partition Key + const partitionKeyProperty = new EntityProperty( + "PartitionKey", + entity.PartitionKey, + new EdmString(entity.PartitionKey), + true + ); + this.properties.push(partitionKeyProperty); + this.propertiesMap.PartitionKey = partitionKeyProperty; + + // Row Key + const rowKeyProperty = new EntityProperty( + "RowKey", + entity.RowKey, + new EdmString(entity.RowKey), + true + ); + this.properties.push(rowKeyProperty); + this.propertiesMap.RowKey = rowKeyProperty; + + // Sync Timestamp from entity last modified time + entity.properties.Timestamp = getTimestampString( + typeof entity.lastModifiedTime === "string" + ? new Date(entity.lastModifiedTime) + : entity.lastModifiedTime + ); + entity.properties["Timestamp@odata.type"] = "Edm.DateTime"; + + for (const key in entity.properties) { + if (Object.prototype.hasOwnProperty.call(entity.properties, key)) { + const element = entity.properties[key]; + if (this.propertiesMap[key] !== undefined) { + continue; + } + + if (key.endsWith(ODATA_TYPE)) { + continue; + } else { + const type = entity.properties[`${key}${ODATA_TYPE}`]; + if (type !== undefined && typeof type !== "string") { + throw RangeError( + `Invalid EdmType value:${type} for key:${key}${ODATA_TYPE}` + ); + } + const property = parseEntityProperty(key, element, type, false); + this.properties.push(property); + this.propertiesMap[key] = property; + } + } + } + } + + // Convert to HTTP response payload string + public toResponseString( + annotationLevel: string, + injections: { [property: string]: string }, + includes?: Set + ): string { + const pairs: string[] = []; + for (const key in injections) { + if (Object.prototype.hasOwnProperty.call(injections, key)) { + const value = injections[key]; + pairs.push(`"${key}":${JSON.stringify(value)}`); + } + } + + for (const pair of this.properties) { + if (!includes || includes.has(pair.name)) { + const str = pair.toResponseString(annotationLevel); + if (str) { + pairs.push(str); + } + } + } + + return `{${pairs.join(",")}}`; + } + + public normalize(): Entity { + this.ref.properties = {}; + for (const entity of this.properties) { + entity.normalize(this.ref); + } + return this.ref; + } +} diff --git a/src/table/errors/StorageError.ts b/src/table/errors/StorageError.ts index d6c4671ab..339f6cbe6 100644 --- a/src/table/errors/StorageError.ts +++ b/src/table/errors/StorageError.ts @@ -41,7 +41,14 @@ export default class StorageError extends MiddlewareError { context?: Context ) { let isJSON = false; - const accept = context ? context.request!.getHeader("accept") : undefined; + let accept = + context && context.request + ? context.request.getHeader("accept") + : undefined; + accept = + context && context.request + ? context.request.getQuery("$format") || accept + : accept; if ( accept === NO_METADATA_ACCEPT || accept === MINIMAL_METADATA_ACCEPT || @@ -77,7 +84,7 @@ export default class StorageError extends MiddlewareError { super( statusCode, storageErrorMessage, - storageErrorMessage, + undefined, { "x-ms-error-code": storageErrorCode, "x-ms-request-id": storageRequestID, diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 28a0b9a78..0574aa2a5 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -26,11 +26,28 @@ export default class StorageErrorFactory { ); } + public static getInvalidInput( + context: Context, + additionalMessages?: { [key: string]: string } + ): StorageError { + if (additionalMessages === undefined) { + additionalMessages = {}; + } + return new StorageError( + 400, + "InvalidInput", + "An error occurred while processing this request.", + context.contextID || defaultID, + additionalMessages, + context + ); + } + public static getTableAlreadyExists(context: Context): StorageError { return new StorageError( 409, "TableAlreadyExists", - "The specified table already exists.", + "The table specified already exists.", context.contextID || defaultID, undefined, context @@ -123,9 +140,9 @@ export default class StorageErrorFactory { public static getTableNotExist(context: Context): StorageError { return new StorageError( - 400, - "AccountNameEmpty", - "The table you want to manipulate doesn't exist", + 404, + "TableNotFound", + "The table specified does not exist.", context.contextID || defaultID, undefined, context @@ -146,7 +163,7 @@ export default class StorageErrorFactory { return new StorageError( 409, "EntityDoesNotExist", - "The entity to update doesn't exist in the table", + "The entity to update doesn't exist in the table.", context.contextID || defaultID, undefined, context @@ -157,7 +174,7 @@ export default class StorageErrorFactory { return new StorageError( 409, "EntityAlreadyExist", - "The entity to insert already exists in the table", + "The specified entity already exists.", context.contextID || defaultID, undefined, context @@ -175,11 +192,11 @@ export default class StorageErrorFactory { ); } - public static getContentTypeNotSupported(context: Context): StorageError { + public static getAtomFormatNotSupported(context: Context): StorageError { return new StorageError( - 400, - "contentTypeNotSupported", - "Payload Type is not supported yet. Only support json.", + 415, + "AtomFormatNotSupported", + "Atom format is not supported.", context.contextID || defaultID, undefined, context @@ -222,8 +239,8 @@ export default class StorageErrorFactory { public static getQueryConditionInvalid(context: Context): StorageError { return new StorageError( 400, - "queryConditionsIncorrect", - "The query condition specified in the request was invalid.", + "InvalidInput", + "The query condition specified in the request is invalid.", context.contextID || defaultID, undefined, context diff --git a/src/table/generated/artifacts/models.ts b/src/table/generated/artifacts/models.ts index 42092b017..3441ef3c6 100644 --- a/src/table/generated/artifacts/models.ts +++ b/src/table/generated/artifacts/models.ts @@ -1520,7 +1520,12 @@ export type TableDeleteResponse = TableDeleteHeaders & { /** * Contains response data for the queryEntities operation. */ -export type TableQueryEntitiesResponse = TableEntityQueryResponse & TableQueryEntitiesHeaders & { +export type TableQueryEntitiesResponse = TableQueryEntitiesHeaders & { + /** + * The response body as a node.js Readable stream. + */ + body?: NodeJS.ReadableStream; +} & { /** * The response status code. */ @@ -1530,7 +1535,12 @@ export type TableQueryEntitiesResponse = TableEntityQueryResponse & TableQueryEn /** * Contains response data for the queryEntitiesWithPartitionAndRowKey operation. */ -export type TableQueryEntitiesWithPartitionAndRowKeyResponse = TableEntityQueryResponse & TableQueryEntitiesWithPartitionAndRowKeyHeaders & { +export type TableQueryEntitiesWithPartitionAndRowKeyResponse = TableQueryEntitiesWithPartitionAndRowKeyHeaders & { + /** + * The response body as a node.js Readable stream. + */ + body?: NodeJS.ReadableStream; +} & { /** * The response status code. */ diff --git a/src/table/generated/artifacts/specifications.ts b/src/table/generated/artifacts/specifications.ts index 2867785a5..24fb37b6a 100644 --- a/src/table/generated/artifacts/specifications.ts +++ b/src/table/generated/artifacts/specifications.ts @@ -20,7 +20,9 @@ const serializer = new msRest.Serializer(Mappers, true); const tableQueryOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "Tables", - urlParameters: [Parameters.url], + urlParameters: [ + Parameters.url + ], queryParameters: [ Parameters.nextTableName, Parameters.format, @@ -47,8 +49,12 @@ const tableQueryOperationSpec: msRest.OperationSpec = { const tableCreateOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "Tables", - urlParameters: [Parameters.url], - queryParameters: [Parameters.format], + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -124,8 +130,14 @@ const tableBatchOperationSpec: msRest.OperationSpec = { const tableDeleteOperationSpec: msRest.OperationSpec = { httpMethod: "DELETE", path: "Tables('{table}')", - urlParameters: [Parameters.url, Parameters.table], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url, + Parameters.table + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], responses: { 204: { headersMapper: Mappers.TableDeleteHeaders @@ -141,7 +153,10 @@ const tableDeleteOperationSpec: msRest.OperationSpec = { const tableQueryEntitiesOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "{table}()", - urlParameters: [Parameters.url, Parameters.table], + urlParameters: [ + Parameters.url, + Parameters.table + ], queryParameters: [ Parameters.timeout, Parameters.nextPartitionKey, @@ -158,7 +173,12 @@ const tableQueryEntitiesOperationSpec: msRest.OperationSpec = { ], responses: { 200: { - bodyMapper: Mappers.TableEntityQueryResponse, + bodyMapper: { + serializedName: "Stream", + type: { + name: "Stream" + } + }, headersMapper: Mappers.TableQueryEntitiesHeaders }, default: { @@ -191,7 +211,12 @@ const tableQueryEntitiesWithPartitionAndRowKeyOperationSpec: msRest.OperationSpe ], responses: { 200: { - bodyMapper: Mappers.TableEntityQueryResponse, + bodyMapper: { + serializedName: "Stream", + type: { + name: "Stream" + } + }, headersMapper: Mappers.TableQueryEntitiesWithPartitionAndRowKeyHeaders }, default: { @@ -211,7 +236,10 @@ const tableUpdateEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [Parameters.timeout, Parameters.format], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -219,7 +247,10 @@ const tableUpdateEntityOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: ["options", "tableEntityProperties"], + parameterPath: [ + "options", + "tableEntityProperties" + ], mapper: { serializedName: "tableEntityProperties", type: { @@ -253,7 +284,10 @@ const tableMergeEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [Parameters.timeout, Parameters.format], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -261,7 +295,10 @@ const tableMergeEntityOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: ["options", "tableEntityProperties"], + parameterPath: [ + "options", + "tableEntityProperties" + ], mapper: { serializedName: "tableEntityProperties", type: { @@ -295,7 +332,10 @@ const tableDeleteEntityOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [Parameters.timeout, Parameters.format], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -323,7 +363,10 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { Parameters.partitionKey, Parameters.rowKey ], - queryParameters: [Parameters.timeout, Parameters.format], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -331,7 +374,10 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { Parameters.ifMatch0 ], requestBody: { - parameterPath: ["options", "tableEntityProperties"], + parameterPath: [ + "options", + "tableEntityProperties" + ], mapper: { serializedName: "tableEntityProperties", type: { @@ -359,8 +405,14 @@ const tableMergeEntityWithMergeOperationSpec: msRest.OperationSpec = { const tableInsertEntityOperationSpec: msRest.OperationSpec = { httpMethod: "POST", path: "{table}", - urlParameters: [Parameters.url, Parameters.table], - queryParameters: [Parameters.timeout, Parameters.format], + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.format + ], headerParameters: [ Parameters.version, Parameters.requestId, @@ -368,7 +420,10 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { Parameters.responsePreference ], requestBody: { - parameterPath: ["options", "tableEntityProperties"], + parameterPath: [ + "options", + "tableEntityProperties" + ], mapper: { serializedName: "tableEntityProperties", type: { @@ -406,9 +461,18 @@ const tableInsertEntityOperationSpec: msRest.OperationSpec = { const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { httpMethod: "GET", path: "{table}", - urlParameters: [Parameters.url, Parameters.table], - queryParameters: [Parameters.timeout, Parameters.comp0], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp0 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], responses: { 200: { bodyMapper: { @@ -437,11 +501,23 @@ const tableGetAccessPolicyOperationSpec: msRest.OperationSpec = { const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { httpMethod: "PUT", path: "{table}", - urlParameters: [Parameters.url, Parameters.table], - queryParameters: [Parameters.timeout, Parameters.comp0], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url, + Parameters.table + ], + queryParameters: [ + Parameters.timeout, + Parameters.comp0 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], requestBody: { - parameterPath: ["options", "tableAcl"], + parameterPath: [ + "options", + "tableAcl" + ], mapper: { xmlName: "SignedIdentifiers", xmlElementName: "SignedIdentifier", @@ -473,9 +549,18 @@ const tableSetAccessPolicyOperationSpec: msRest.OperationSpec = { // specifications for new method group start const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { httpMethod: "PUT", - urlParameters: [Parameters.url], - queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp1], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp1 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], requestBody: { parameterPath: "tableServiceProperties", mapper: { @@ -498,9 +583,18 @@ const serviceSetPropertiesOperationSpec: msRest.OperationSpec = { const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { httpMethod: "GET", - urlParameters: [Parameters.url], - queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp1], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp1 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], responses: { 200: { bodyMapper: Mappers.TableServiceProperties, @@ -516,9 +610,18 @@ const serviceGetPropertiesOperationSpec: msRest.OperationSpec = { const serviceGetStatisticsOperationSpec: msRest.OperationSpec = { httpMethod: "GET", - urlParameters: [Parameters.url], - queryParameters: [Parameters.timeout, Parameters.restype, Parameters.comp2], - headerParameters: [Parameters.version, Parameters.requestId], + urlParameters: [ + Parameters.url + ], + queryParameters: [ + Parameters.timeout, + Parameters.restype, + Parameters.comp2 + ], + headerParameters: [ + Parameters.version, + Parameters.requestId + ], responses: { 200: { bodyMapper: Mappers.TableServiceStats, @@ -538,29 +641,15 @@ Specifications[Operation.Table_Create] = tableCreateOperationSpec; Specifications[Operation.Table_Batch] = tableBatchOperationSpec; Specifications[Operation.Table_Delete] = tableDeleteOperationSpec; Specifications[Operation.Table_QueryEntities] = tableQueryEntitiesOperationSpec; -Specifications[ - Operation.Table_QueryEntitiesWithPartitionAndRowKey -] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; +Specifications[Operation.Table_QueryEntitiesWithPartitionAndRowKey] = tableQueryEntitiesWithPartitionAndRowKeyOperationSpec; Specifications[Operation.Table_UpdateEntity] = tableUpdateEntityOperationSpec; Specifications[Operation.Table_MergeEntity] = tableMergeEntityOperationSpec; Specifications[Operation.Table_DeleteEntity] = tableDeleteEntityOperationSpec; -Specifications[ - Operation.Table_MergeEntityWithMerge -] = tableMergeEntityWithMergeOperationSpec; +Specifications[Operation.Table_MergeEntityWithMerge] = tableMergeEntityWithMergeOperationSpec; Specifications[Operation.Table_InsertEntity] = tableInsertEntityOperationSpec; -Specifications[ - Operation.Table_GetAccessPolicy -] = tableGetAccessPolicyOperationSpec; -Specifications[ - Operation.Table_SetAccessPolicy -] = tableSetAccessPolicyOperationSpec; -Specifications[ - Operation.Service_SetProperties -] = serviceSetPropertiesOperationSpec; -Specifications[ - Operation.Service_GetProperties -] = serviceGetPropertiesOperationSpec; -Specifications[ - Operation.Service_GetStatistics -] = serviceGetStatisticsOperationSpec; +Specifications[Operation.Table_GetAccessPolicy] = tableGetAccessPolicyOperationSpec; +Specifications[Operation.Table_SetAccessPolicy] = tableSetAccessPolicyOperationSpec; +Specifications[Operation.Service_SetProperties] = serviceSetPropertiesOperationSpec; +Specifications[Operation.Service_GetProperties] = serviceGetPropertiesOperationSpec; +Specifications[Operation.Service_GetStatistics] = serviceGetStatisticsOperationSpec; export default Specifications; diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 744fbfbb8..1a0e8bf27 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -1,133 +1,110 @@ import BufferStream from "../../common/utils/BufferStream"; import { newEtag } from "../../common/utils/utils"; import TableStorageContext from "../context/TableStorageContext"; +import { NormalizedEntity } from "../entity/NormalizedEntity"; import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; import * as Models from "../generated/artifacts/models"; import Context from "../generated/Context"; import ITableHandler from "../generated/handlers/ITableHandler"; -import { IEntity, TableModel } from "../persistence/ITableMetadataStore"; +import { Entity, Table } from "../persistence/ITableMetadataStore"; import { DEFAULT_TABLE_LISTENING_PORT, DEFAULT_TABLE_SERVER_HOST_NAME, FULL_METADATA_ACCEPT, + HeaderConstants, MINIMAL_METADATA_ACCEPT, NO_METADATA_ACCEPT, - QUERY_RESULT_MAX_NUM, RETURN_CONTENT, RETURN_NO_CONTENT, - TABLE_API_VERSION + TABLE_API_VERSION, + XML_METADATA } from "../utils/constants"; +import { + getEntityOdataAnnotationsForResponse, + getTableOdataAnnotationsForResponse, + getTablePropertiesOdataAnnotationsForResponse, + updateTableOptionalOdataAnnotationsForResponse +} from "../utils/utils"; import BaseHandler from "./BaseHandler"; -export default class TableHandler extends BaseHandler implements ITableHandler { - public async batch( - body: NodeJS.ReadableStream, - multipartContentType: string, - contentLength: number, - options: Models.TableBatchOptionalParams, - context: Context - ): Promise { - const tableCtx = new TableStorageContext(context); - // TODO: Implement batch operation logic here - return { - requestId: tableCtx.contextID, - version: TABLE_API_VERSION, - date: context.startTime, - statusCode: 202, - body // Use incoming request body as Batch operation response body as demo - }; - } +interface IPartialResponsePreferProperties { + statusCode: 200 | 201 | 204; + preferenceApplied?: string; +} +/** + * TODO: + * 1. Check Accept for every API + * 2. Check Prefer for every API + */ + +export default class TableHandler extends BaseHandler implements ITableHandler { public async create( tableProperties: Models.TableProperties, options: Models.TableCreateOptionalParams, context: Context ): Promise { - const tableCtx = new TableStorageContext(context); - const accountName = tableCtx.account; - - const accept = context.request!.getHeader("accept"); - - if ( - accept !== NO_METADATA_ACCEPT && - accept !== MINIMAL_METADATA_ACCEPT && - accept !== FULL_METADATA_ACCEPT - ) { - throw StorageErrorFactory.getContentTypeNotSupported(context); - } - - if (accountName === undefined) { - throw StorageErrorFactory.getAccountNameEmpty(context); - } - - // Here table name is in request body, not in url - const tableName = tableProperties.tableName; - if (tableName === undefined) { - throw StorageErrorFactory.getTableNameEmpty; + const tableContext = new TableStorageContext(context); + const accept = this.getAndCheckPayloadFormat(tableContext); + const account = this.getAndCheckAccountName(tableContext); + const table = tableProperties.tableName; // Table name is in request body instead of URL + if (table === undefined) { + throw StorageErrorFactory.getTableNameEmpty(context); } - const metadata = `${accountName}/$metadata#Tables/@Element`; - const type = `${accountName}.Tables`; - const id = `${accountName}/Tables(${tableName})`; - const editLink = `Tables(${tableName})`; - - const table: TableModel = { - account: accountName, - tableName, - odatametadata: metadata, - odatatype: type, - odataid: id, - odataeditLink: editLink + const tableModel: Table = { + account, + table }; - await this.metadataStore.createTable(context, table); + await this.metadataStore.createTable(context, tableModel); const response: Models.TableCreateResponse = { clientRequestId: options.requestId, - requestId: tableCtx.contextID, + requestId: tableContext.contextID, version: TABLE_API_VERSION, date: context.startTime, - statusCode: 204 + statusCode: 201 }; - if (context.request!.getHeader("Prefer") === RETURN_NO_CONTENT) { - response.statusCode = 204; - response.preferenceApplied = RETURN_NO_CONTENT; - } + response.tableName = table; + updateTableOptionalOdataAnnotationsForResponse( + response, + account, + table, + this.getOdataAnnotationUrlPrefix(tableContext, account), + accept + ); - if (context.request!.getHeader("Prefer") === RETURN_CONTENT) { - response.statusCode = 201; - response.preferenceApplied = "return-content"; - } + this.updateResponsePrefer(response, tableContext); + this.updateResponseAccept(tableContext, accept); - let protocol = "http"; - let host = - DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; - // TODO: Get host and port from Azurite Server instance - if (tableCtx.request !== undefined) { - host = tableCtx.request.getHeader("host") as string; - protocol = tableCtx.request.getProtocol() as string; - } + return response; + } - if (tableCtx.accept === NO_METADATA_ACCEPT) { - response.tableName = tableName; - } + public async delete( + _table: string, + options: Models.TableDeleteMethodOptionalParams, + context: Context + ): Promise { + const tableContext = new TableStorageContext(context); + const account = this.getAndCheckAccountName(tableContext); + const table = this.getAndCheckTableName(tableContext); + const accept = this.getAndCheckPayloadFormat(tableContext); - if (tableCtx.accept === MINIMAL_METADATA_ACCEPT) { - response.tableName = tableName; - response.odatametadata = `${protocol}://${host}/${metadata}`; - } + await this.metadataStore.deleteTable(context, table, account!); - if (tableCtx.accept === FULL_METADATA_ACCEPT) { - response.tableName = tableName; - response.odatametadata = `${protocol}://${host}/${metadata}`; - response.odatatype = type; - response.odataid = `${protocol}://${host}/${id}`; - response.odataeditLink = editLink; - } + const response: Models.TableDeleteResponse = { + clientRequestId: options.requestId, + requestId: tableContext.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode: 204 + }; + + this.updateResponseAccept(tableContext, accept); - context.response!.setContentType(accept); return response; } @@ -135,185 +112,139 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableQueryOptionalParams, context: Context ): Promise { - const tableCtx = new TableStorageContext(context); - const accountName = tableCtx.account; + const tableContext = new TableStorageContext(context); + const account = this.getAndCheckAccountName(tableContext); + const accept = this.getAndCheckPayloadFormat(tableContext); - const accept = context.request!.getHeader("accept"); - - if ( - accept !== NO_METADATA_ACCEPT && - accept !== MINIMAL_METADATA_ACCEPT && - accept !== FULL_METADATA_ACCEPT - ) { - throw StorageErrorFactory.getContentTypeNotSupported(context); - } - - if (accountName === undefined) { - throw StorageErrorFactory.getAccountNameEmpty(context); - } - - const metadata = `${accountName}/$metadata#Tables`; - const tableResult = await this.metadataStore.queryTable( + const [tableResult, nextTableName] = await this.metadataStore.queryTable( context, - accountName + account, + options.queryOptions?.top, + options.nextTableName ); const response: Models.TableQueryResponse2 = { clientRequestId: options.requestId, - requestId: tableCtx.contextID, + requestId: tableContext.contextID, version: TABLE_API_VERSION, date: context.startTime, statusCode: 200, - xMsContinuationNextTableName: options.nextTableName, + xMsContinuationNextTableName: nextTableName, value: [] }; - let protocol = "http"; - let host = - DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; - // TODO: Get host and port from Azurite Server instance - if (tableCtx.request !== undefined) { - host = tableCtx.request.getHeader("host") as string; - protocol = tableCtx.request.getProtocol() as string; - } + const prefix = this.getOdataAnnotationUrlPrefix(tableContext, account); + const annotation = getTableOdataAnnotationsForResponse(account, "", prefix); - if (tableCtx.accept === NO_METADATA_ACCEPT) { - response.value = tableResult.map(item => { - return { tableName: item.tableName }; - }); + if (accept === MINIMAL_METADATA_ACCEPT || accept === FULL_METADATA_ACCEPT) { + response.odatametadata = annotation.odatametadata; } - if (tableCtx.accept === MINIMAL_METADATA_ACCEPT) { - response.odatametadata = `${protocol}://${host}/${metadata}`; - response.value = tableResult.map(item => { - return { tableName: item.tableName }; - }); - } - - if (tableCtx.accept === FULL_METADATA_ACCEPT) { - response.odatametadata = `${protocol}://${host}/${metadata}`; - response.value = tableResult.map(item => { - return { - odatatype: item.odatatype, - odataid: `${protocol}://${host}/${item.odataid}`, - odataeditLink: item.odataeditLink, - tableName: item.tableName - }; - }); - } + response.value = tableResult.map((item) => + getTablePropertiesOdataAnnotationsForResponse( + item.table, + account, + prefix, + accept + ) + ); - context.response!.setContentType(accept); + this.updateResponseAccept(tableContext, accept); return response; } - public async delete( - tablename: string, - options: Models.TableDeleteMethodOptionalParams, + // TODO: Filter odata types per accept settings + public async insertEntity( + _tableName: string, + options: Models.TableInsertEntityOptionalParams, context: Context - ): Promise { - const tableCtx = new TableStorageContext(context); - const accountName = tableCtx.account; - // currently the tableName is not coming through, so we take it from the table context - await this.metadataStore.deleteTable( - context, - tableCtx.tableName!, - accountName! - ); - const response: Models.TableDeleteResponse = { - clientRequestId: options.requestId, - requestId: tableCtx.contextID, - version: TABLE_API_VERSION, - date: context.startTime, - statusCode: 204 - }; + ): Promise { + const tableContext = new TableStorageContext(context); + const account = this.getAndCheckAccountName(tableContext); + const table = this.getAndCheckTableName(tableContext); + const accept = this.getAndCheckPayloadFormat(tableContext); + const prefer = this.getAndCheckPreferHeader(tableContext); - return response; - } + if ( + !options.tableEntityProperties || + !options.tableEntityProperties.PartitionKey || + !options.tableEntityProperties.RowKey + ) { + throw StorageErrorFactory.getPropertiesNeedValue(context); + } - public async queryEntities( - table: string, - options: Models.TableQueryEntitiesOptionalParams, - context: Context - ): Promise { - const tableCtx = new TableStorageContext(context); - const tableName = tableCtx.tableName; - const accountName = tableCtx.account; + const entity: Entity = { + PartitionKey: options.tableEntityProperties.PartitionKey, + RowKey: options.tableEntityProperties.RowKey, + properties: options.tableEntityProperties, + lastModifiedTime: context.startTime!, + eTag: newEtag() + }; - const result = await this.metadataStore.queryTableEntities( - context, - accountName!, - tableName!, - options.queryOptions! - ); + let nomarlizedEntity; + try { + nomarlizedEntity = new NormalizedEntity(entity); + nomarlizedEntity.normalize(); + } catch (e) { + this.logger.error( + `TableHandler:insertEntity() ${e.name} ${JSON.stringify(e.stack)}`, + context.contextID + ); + throw StorageErrorFactory.getInvalidInput(context); + } - const response: Models.TableQueryEntitiesResponse = { + await this.metadataStore.insertTableEntity(context, table, account, entity); + + const response: Models.TableInsertEntityResponse = { clientRequestId: options.requestId, - requestId: tableCtx.contextID, + requestId: tableContext.contextID, version: TABLE_API_VERSION, date: context.startTime, - statusCode: 200 + statusCode: 201, + eTag: entity.eTag }; - const responseBody = this.getResponseBodyFromQueryResultBasedOnAccept( - tableCtx.accept!, - accountName!, - tableCtx, - result - ); + if (prefer === RETURN_CONTENT || prefer === undefined) { + const body = {} as any; + const annotation = getEntityOdataAnnotationsForResponse( + account, + table, + this.getOdataAnnotationUrlPrefix(tableContext, account), + options.tableEntityProperties.PartitionKey, + options.tableEntityProperties.RowKey, + accept + ); - // Set query result - response.value = responseBody.value; - if (responseBody["odata.metadata"] !== undefined) { - response.odatametadata = responseBody["odata.metadata"]; - } + if (accept === MINIMAL_METADATA_ACCEPT) { + body["odata.metadata"] = annotation.odatametadata; + body["odata.etag"] = entity.eTag; + } - // Set x-ms-continuation-NextPartitionKey and x-ms-continuation-NextRowKey - if (result.length > QUERY_RESULT_MAX_NUM) { - response.xMsContinuationNextPartitionKey = - result[QUERY_RESULT_MAX_NUM].PartitionKey; - response.xMsContinuationNextRowKey = result[QUERY_RESULT_MAX_NUM].RowKey; + if (accept === FULL_METADATA_ACCEPT) { + body["odata.metadata"] = annotation.odatametadata; + body["odata.type"] = annotation.odatatype; + body["odata.id"] = annotation.odataid; + body["odata.etag"] = entity.eTag; + body["odata.editLink"] = annotation.odataeditLink; + } + + // for (const key of Object.keys(entity.properties)) { + // body[key] = entity.properties[key]; + // } + + // response.body = new BufferStream(Buffer.from(JSON.stringify(body))); + response.body = new BufferStream( + Buffer.from(nomarlizedEntity.toResponseString(accept, body)) + ); } - return response; - } + response.contentType = "application/json"; + this.updateResponsePrefer(response, tableContext); - public async queryEntitiesWithPartitionAndRowKey( - _table: string, - _partitionKey: string, - _rowKey: string, - options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, - context: Context - ): Promise { - // e.g - // const tableCtx = new TableStorageContext(context); - // const accountName = tableCtx.account; - // const tableName = tableCtx.tableName; // Get tableName from context - // const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context - // const rowKey = tableCtx.rowKey!; // Get rowKey from context - // return { - // statusCode: 200, - // date: tableCtx.startTime, - // clientRequestId: "clientRequestId", - // requestId: "requestId", - // version: "version", - // xMsContinuationNextPartitionKey: partitionKeyFromContext, - // xMsContinuationNextRowKey: rowKeyFromContext, - // odatametadata: "odatametadata", - // value: [ - // { - // property1: "property1" + accountName, - // property2: "property2" + tableName, - // property3: "property3" - // }, - // { - // property1: "property1" - // } - // ] - // }; - // TODO - throw new NotImplementedError(); + return response; } + // TODO: Create data structures to hold entity properties and support serialize, merge, deserialize, filter public async updateEntity( _table: string, _partitionKey: string, @@ -321,18 +252,24 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableUpdateEntityOptionalParams, context: Context ): Promise { - const tableCtx = new TableStorageContext(context); - const accountName = tableCtx.account; - const tableName = tableCtx.tableName!; // Get tableName from context + const tableContext = new TableStorageContext(context); + const account = this.getAndCheckAccountName(tableContext); + const table = this.getAndCheckTableName(tableContext); + const partitionKey = this.getAndCheckPartitionKey(tableContext); + const rowKey = this.getAndCheckRowKey(tableContext); const ifMatch = options.ifMatch; - // Test if all required parameter exist + if (!options.tableEntityProperties) { + throw StorageErrorFactory.getPropertiesNeedValue(context); + } + if ( - !options.tableEntityProperties || - !options.tableEntityProperties.PartitionKey || - !options.tableEntityProperties.RowKey + options.tableEntityProperties.PartitionKey !== partitionKey || + options.tableEntityProperties.RowKey !== rowKey ) { - throw StorageErrorFactory.getPropertiesNeedValue(context); + this.logger.warn( + `TableHandler:updateEntity() Incoming PartitionKey:${partitionKey} RowKey:${rowKey} in URL parameters don't align with entity body PartitionKey:${options.tableEntityProperties.PartitionKey} RowKey:${options.tableEntityProperties.RowKey}.` + ); } // Test if etag is available @@ -342,70 +279,44 @@ export default class TableHandler extends BaseHandler implements ITableHandler { throw StorageErrorFactory.getPreconditionFailed(context); } - const metadata = `${accountName}/$metadata#Tables/@Element`; - const type = `${accountName}.Tables`; - const id = `Tables(${tableName})`; - const editLink = `Tables(${tableName})`; - - const updateEtag = newEtag(); + const eTag = newEtag(); // Entity, which is used to update an existing entity - const entity: IEntity = { - PartitionKey: options.tableEntityProperties.PartitionKey, - RowKey: options.tableEntityProperties.RowKey, + const entity: Entity = { + PartitionKey: partitionKey, + RowKey: rowKey, properties: options.tableEntityProperties, lastModifiedTime: context.startTime!, - odataMetadata: metadata, - odataType: type, - odataId: id, - odataEditLink: editLink - eTag: updateEtag + eTag }; - if (ifMatch !== undefined) { - // Update entity - await this.metadataStore.updateTableEntity( - context, - tableName, - accountName!, - entity, - ifMatch! + let nomarlizedEntity; + try { + nomarlizedEntity = new NormalizedEntity(entity); + nomarlizedEntity.normalize(); + } catch (e) { + this.logger.error( + `TableHandler:updateEntity() ${e.name} ${JSON.stringify(e.stack)}`, + context.contextID ); - } else { - // Upsert the entity - const exists = await this.metadataStore.queryTableEntitiesWithPartitionAndRowKey( - context, - tableName, - accountName!, - options.tableEntityProperties.PartitionKey, - options.tableEntityProperties.RowKey - ); - - if (exists !== null) { - // entity exists so we update and force with "*" etag - await this.metadataStore.updateTableEntity( - context, - tableName, - accountName!, - entity, - "*" - ); - } else { - await this.metadataStore.insertTableEntity( - context, - tableName, - accountName!, - entity - ); - } + throw StorageErrorFactory.getInvalidInput(context); } + + await this.metadataStore.insertOrUpdateTableEntity( + context, + table, + account, + entity, + ifMatch + ); + // Response definition const response: Models.TableUpdateEntityResponse = { clientRequestId: options.requestId, - requestId: tableCtx.contextID, + requestId: tableContext.contextID, version: TABLE_API_VERSION, date: context.startTime, - eTag: updateEtag, + eTag, statusCode: 204 }; @@ -419,92 +330,67 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableMergeEntityOptionalParams, context: Context ): Promise { - const tableCtx = new TableStorageContext(context); - const accountName = tableCtx.account; - const tableName = tableCtx.tableName; - const partitionKey = tableCtx.partitionKey!; - const rowKey = tableCtx.rowKey!; + const tableContext = new TableStorageContext(context); + const account = this.getAndCheckAccountName(tableContext); + const table = this.getAndCheckTableName(tableContext); + const partitionKey = this.getAndCheckPartitionKey(tableContext); + const rowKey = this.getAndCheckRowKey(tableContext); - if ( - !options.tableEntityProperties || - !options.tableEntityProperties.PartitionKey || - !options.tableEntityProperties.RowKey - ) { + if (!options.tableEntityProperties) { throw StorageErrorFactory.getPropertiesNeedValue(context); } - const existingEntity = await this.metadataStore.queryTableEntitiesWithPartitionAndRowKey( - context, - tableName!, - accountName!, - partitionKey, - rowKey - ); - let etagValue = "*"; - - if (existingEntity !== null) { - const mergeEntity: IEntity = { - PartitionKey: options.tableEntityProperties.PartitionKey, - RowKey: options.tableEntityProperties.RowKey, - properties: options.tableEntityProperties, - lastModifiedTime: context.startTime!, - eTag: etagValue - }; - - etagValue = await this.metadataStore.mergeTableEntity( - context, - tableName!, - accountName!, - mergeEntity, - etagValue, - partitionKey, - rowKey + if ( + options.tableEntityProperties.PartitionKey !== partitionKey || + options.tableEntityProperties.RowKey !== rowKey + ) { + this.logger.warn( + `TableHandler:mergeEntity() Incoming PartitionKey:${partitionKey} RowKey:${rowKey} in URL parameters don't align with entity body PartitionKey:${options.tableEntityProperties.PartitionKey} RowKey:${options.tableEntityProperties.RowKey}.` ); - } else { - const entity: IEntity = { - PartitionKey: options.tableEntityProperties.PartitionKey, - RowKey: options.tableEntityProperties.RowKey, - properties: options.tableEntityProperties, - lastModifiedTime: context.startTime!, - eTag: etagValue - }; - - await this.metadataStore.insertTableEntity( - context, - tableName!, - accountName!, - entity + } + + const eTag = newEtag(); + + const entity: Entity = { + PartitionKey: partitionKey, + RowKey: rowKey, + properties: options.tableEntityProperties, + lastModifiedTime: context.startTime!, + eTag + }; + + let nomarlizedEntity; + try { + nomarlizedEntity = new NormalizedEntity(entity); + nomarlizedEntity.normalize(); + } catch (e) { + this.logger.error( + `TableHandler:mergeEntity() ${e.name} ${JSON.stringify(e.stack)}`, + context.contextID ); + throw StorageErrorFactory.getInvalidInput(context); } + await this.metadataStore.insertOrMergeTableEntity( + context, + table, + account, + entity, + options.ifMatch + ); + const response: Models.TableMergeEntityResponse = { clientRequestId: options.requestId, - requestId: tableCtx.contextID, + requestId: tableContext.contextID, version: TABLE_API_VERSION, date: context.startTime, statusCode: 204, - eTag: etagValue + eTag }; return response; } - public async mergeEntityWithMerge( - table: string, - partitionKey: string, - rowKey: string, - options: Models.TableMergeEntityWithMergeOptionalParams, - context: Context - ): Promise { - return this.mergeEntity( - table, - partitionKey, - rowKey, - options as any, - context - ); - } - public async deleteEntity( _table: string, _partitionKey: string, @@ -513,10 +399,10 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableDeleteEntityOptionalParams, context: Context ): Promise { - const tableCtx = new TableStorageContext(context); - const accountName = tableCtx.account; - const partitionKey = tableCtx.partitionKey!; // Get partitionKey from context - const rowKey = tableCtx.rowKey!; // Get rowKey from context + const tableContext = new TableStorageContext(context); + const accountName = tableContext.account; + const partitionKey = tableContext.partitionKey!; // Get partitionKey from context + const rowKey = tableContext.rowKey!; // Get rowKey from context if (!partitionKey || !rowKey) { throw StorageErrorFactory.getPropertiesNeedValue(context); @@ -527,7 +413,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { // currently the props are not coming through as args, so we take them from the table context await this.metadataStore.deleteTableEntity( context, - tableCtx.tableName!, + tableContext.tableName!, accountName!, partitionKey, rowKey, @@ -536,126 +422,209 @@ export default class TableHandler extends BaseHandler implements ITableHandler { return { statusCode: 204, - date: tableCtx.startTime, + date: tableContext.startTime, clientRequestId: options.requestId, - requestId: tableCtx.contextID, + requestId: tableContext.contextID, version: TABLE_API_VERSION }; } - public async insertEntity( - _tableName: string, - options: Models.TableInsertEntityOptionalParams, + public async queryEntities( + _table: string, + options: Models.TableQueryEntitiesOptionalParams, context: Context - ): Promise { - const tableCtx = new TableStorageContext(context); - const accountName = tableCtx.account; - const tableName = tableCtx.tableName!; // Get tableName from context - - if ( - !options.tableEntityProperties || - !options.tableEntityProperties.PartitionKey || - !options.tableEntityProperties.RowKey - ) { - throw StorageErrorFactory.getPropertiesNeedValue(context); - } - - const metadata = `${accountName}/$metadata#Tables/@Element`; - const type = `${accountName}.${tableName}`; - const id = - `${tableName}` + - `(PartitionKey='${options.tableEntityProperties.PartitionKey}',` + - `RowKey='${options.tableEntityProperties.RowKey}')`; - const editLink = id; - - const entity: IEntity = { - PartitionKey: options.tableEntityProperties.PartitionKey, - RowKey: options.tableEntityProperties.RowKey, - properties: options.tableEntityProperties, - lastModifiedTime: context.startTime!, - eTag: newEtag(), - odataMetadata: metadata, // Here we store value without protocol and host - odataType: type, - odataId: id, - odataEditLink: editLink - }; - - await this.metadataStore.insertTableEntity( + ): Promise { + const tableContext = new TableStorageContext(context); + const table = this.getAndCheckTableName(tableContext); + const account = this.getAndCheckAccountName(tableContext); + const accept = this.getAndCheckPayloadFormat(tableContext); + + const [ + result, + nextPartitionKey, + nextRowKey + ] = await this.metadataStore.queryTableEntities( context, - tableName, - accountName!, - entity + account, + table, + options.queryOptions || {}, + options.nextPartitionKey, + options.nextRowKey ); - const response: Models.TableInsertEntityResponse = { + const response: Models.TableQueryEntitiesResponse = { clientRequestId: options.requestId, - requestId: tableCtx.contextID, + requestId: tableContext.contextID, version: TABLE_API_VERSION, date: context.startTime, - statusCode: 201 + xMsContinuationNextPartitionKey: nextPartitionKey, + xMsContinuationNextRowKey: nextRowKey, + statusCode: 200 }; - const accept = tableCtx.accept; - - // Set contentType in response according to accept - if ( - accept !== NO_METADATA_ACCEPT && - accept !== MINIMAL_METADATA_ACCEPT && - accept !== FULL_METADATA_ACCEPT - ) { - throw StorageErrorFactory.getContentTypeNotSupported(context); + let selectSet: Set | undefined; + const selectArray = options.queryOptions?.select + ?.split(",") + .map((item) => item.trim()); + if (selectArray) { + selectSet = new Set(selectArray); } - response.contentType = "application/json"; - const body = {} as any; - - if (context.request!.getHeader("Prefer") === RETURN_NO_CONTENT) { - response.statusCode = 204; - response.preferenceApplied = RETURN_NO_CONTENT; - } + const entities: string[] = []; + result.forEach((element) => { + const entity = {} as any; + const annotation = getEntityOdataAnnotationsForResponse( + account, + table, + this.getOdataAnnotationUrlPrefix(tableContext, account), + element.PartitionKey, + element.RowKey, + accept + ); - if (context.request!.getHeader("Prefer") === RETURN_CONTENT) { - response.statusCode = 201; - response.preferenceApplied = "return-content"; - - let protocol = "http"; - let host = - DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; - if (tableCtx.request !== undefined) { - host = tableCtx.request.getHeader("host") as string; - protocol = tableCtx.request.getProtocol() as string; - } - - if (accept === MINIMAL_METADATA_ACCEPT) { - body["odata.metadata"] = `${protocol}://${host}/` + metadata; + if ( + accept === MINIMAL_METADATA_ACCEPT || + accept === FULL_METADATA_ACCEPT + ) { + entity["odata.etag"] = element.eTag; } if (accept === FULL_METADATA_ACCEPT) { - body["odata.metadata"] = `${protocol}://${host}/` + metadata; - body["odata.type"] = type; - body["body.id"] = `${protocol}://${host}/` + id; - body["odata.etag"] = entity.eTag; - body["odata.editLink"] = editLink; + entity["odata.type"] = annotation.odatatype; + entity["odata.id"] = annotation.odataid; + entity["odata.editLink"] = annotation.odataeditLink; } - for (const key of Object.keys(entity.properties)) { - body[key] = entity.properties[key]; - } + const nomarlizedEntity = new NormalizedEntity(element); + entities.push( + nomarlizedEntity.toResponseString(accept, entity, selectSet) + ); + }); + + const odatametadata = + getEntityOdataAnnotationsForResponse( + account, + table, + this.getOdataAnnotationUrlPrefix(tableContext, account), + "", + "element.RowKey", + accept + ).odatametadata || ""; + + const body = `{"odata.metadata":${JSON.stringify( + odatametadata + )},"value":[${entities.join(",")}]}`; + response.body = new BufferStream(Buffer.from(body)); + + this.logger.debug( + `QueryEntities response body: ${body}`, + context.contextID + ); + + context.response!.setContentType("application/json"); + + return response; + } + + public async queryEntitiesWithPartitionAndRowKey( + _table: string, + _partitionKey: string, + _rowKey: string, + options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, + context: Context + ): Promise { + const tableContext = new TableStorageContext(context); + const account = this.getAndCheckAccountName(tableContext); + const table = this.getAndCheckTableName(tableContext); + const partitionKey = this.getAndCheckPartitionKey(tableContext); + const rowKey = this.getAndCheckRowKey(tableContext); + const accept = this.getAndCheckPayloadFormat(tableContext); + + const entity = await this.metadataStore.queryTableEntitiesWithPartitionAndRowKey( + context, + table, + account, + partitionKey, + rowKey + ); + + if (entity === undefined || entity === null) { + throw StorageErrorFactory.getEntityNotExist(context); + } + + const response: Models.TableQueryEntitiesWithPartitionAndRowKeyResponse = { + statusCode: 200, + date: tableContext.startTime, + clientRequestId: options.requestId, + requestId: context.contextID, + version: TABLE_API_VERSION + }; + + const body = {} as any; + const annotation = getEntityOdataAnnotationsForResponse( + account, + table, + this.getOdataAnnotationUrlPrefix(tableContext, account), + partitionKey, + rowKey, + accept + ); + + if (accept === MINIMAL_METADATA_ACCEPT) { + body["odata.metadata"] = annotation.odatametadata; + body["odata.etag"] = entity.eTag; + } + + if (accept === FULL_METADATA_ACCEPT) { + body["odata.metadata"] = annotation.odatametadata; + body["odata.type"] = annotation.odatatype; + body["odata.id"] = annotation.odataid; + body["odata.etag"] = entity.eTag; + body["odata.editLink"] = annotation.odataeditLink; + } - response.body = new BufferStream(Buffer.from(JSON.stringify(body))); + let selectSet: Set | undefined; + const selectArray = options.queryOptions?.select + ?.split(",") + .map((item) => item.trim()); + if (selectArray) { + selectSet = new Set(selectArray); } + + const nomarlizedEntity = new NormalizedEntity(entity); + response.body = new BufferStream( + Buffer.from(nomarlizedEntity.toResponseString(accept, body, selectSet)) + ); + + context.response!.setContentType("application/json"); return response; } + public async mergeEntityWithMerge( + table: string, + partitionKey: string, + rowKey: string, + options: Models.TableMergeEntityWithMergeOptionalParams, + context: Context + ): Promise { + return this.mergeEntity( + table, + partitionKey, + rowKey, + options as any, + context + ); + } + public async getAccessPolicy( table: string, options: Models.TableGetAccessPolicyOptionalParams, context: Context ): Promise { // e.g - // const tableCtx = new TableStorageContext(context); - // const accountName = tableCtx.account; - // const tableName = tableCtx.tableName; // Get tableName from context + // const tableContext = new TableStorageContext(context); + // const accountName = tableContext.account; + // const tableName = tableContext.tableName; // Get tableName from context // TODO throw new NotImplementedError(); } @@ -666,122 +635,252 @@ export default class TableHandler extends BaseHandler implements ITableHandler { context: Context ): Promise { // e.g - // const tableCtx = new TableStorageContext(context); - // const accountName = tableCtx.account; - // const tableName = tableCtx.tableName; // Get tableName from context + // const tableContext = new TableStorageContext(context); + // const accountName = tableContext.account; + // const tableName = tableContext.tableName; // Get tableName from context // TODO throw new NotImplementedError(); } - private getResponseBodyFromQueryResultBasedOnAccept( - accept: string, - accountName: string, - tableCtx: Context, - queryResult: { [propertyName: string]: any }[] - ) { + public async batch( + body: NodeJS.ReadableStream, + multipartContentType: string, + contentLength: number, + options: Models.TableBatchOptionalParams, + context: Context + ): Promise { + const tableContext = new TableStorageContext(context); + // TODO: Implement batch operation logic here + return { + requestId: tableContext.contextID, + version: TABLE_API_VERSION, + date: context.startTime, + statusCode: 202, + body // Use incoming request body as Batch operation response body as demo + }; + } + + // private getResponseBodyFromQueryResultBasedOnAccept( + // accept: string, + // accountName: string, + // tableContext: Context, + // queryResult: { [propertyName: string]: any }[] + // ) { + // let protocol = "http"; + // let host = + // DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; + + // if (tableContext.request !== undefined) { + // host = tableContext.request.getHeader("host") as string; + // protocol = tableContext.request.getProtocol() as string; + // } + + // const resultWithMetaData: { [propertyName: string]: any }[] = []; + // const responseBody: { [propertyName: string]: any } = {}; + + // switch (accept) { + // case MINIMAL_METADATA_ACCEPT: { + // // Add odata.metadata + // (responseBody as any)["odata.metadata"] = + // `${protocol}://${host}/` + queryResult[0].odataMetadata; + // for (const entity of queryResult) { + // const filteredEntity = {}; + // for (const key of Object.keys(entity)) { + // // Only need metadata and properties' odata type + // if ( + // key === "odataMetadata" || + // key === "odataType" || + // key === "odataId" || + // key === "eTag" || + // key === "odataEditLink" + // ) { + // continue; + // } + // // Also add odataType to each field + // (filteredEntity as any)[key] = entity[key]; + // } + + // resultWithMetaData.push(filteredEntity); + // } + // (responseBody as any).value = resultWithMetaData; + // break; + // } + // case FULL_METADATA_ACCEPT: { + // // Add odata.metadata + // (responseBody as any)["odata.metadata"] = queryResult[0].odataMetadata; + // for (const entity of queryResult) { + // const filteredEntity = {}; + // for (const key of Object.keys(entity)) { + // // Remove odataMetadata of each entity + // if (key === "odataMetadata") { + // continue; + // } + // (filteredEntity as any)[key] = entity[key]; + // } + + // // Add Timestamp@odata.type + // (filteredEntity as any)["Timestamp@odata.type"] = "Edm.DateTime"; + + // // Solve the name inconsistency of the response and entity + // (filteredEntity as any)[ + // "odata.type" + // ] = (filteredEntity as any).odataType; + // delete (filteredEntity as any).odataType; + + // (filteredEntity as any)["odata.id"] = + // `${protocol}://${host}/` + (filteredEntity as any).odataId; + // delete (filteredEntity as any).odataId; + + // (filteredEntity as any)["odata.etag"] = (filteredEntity as any).eTag; + // delete (filteredEntity as any).eTag; + + // (filteredEntity as any)[ + // "odata.editLink" + // ] = (filteredEntity as any).odataEditLink; + // delete (filteredEntity as any).odataEditLink; + + // // Add processed entity back + // resultWithMetaData.push(filteredEntity); + // } + // (responseBody as any).value = resultWithMetaData; + // break; + // } + // default: { + // for (const entity of queryResult) { + // const filteredEntity = {}; + // for (const key of Object.keys(entity)) { + // // Don't need metadata and properties' odata type + // if ( + // key === "odataMetadata" || + // key === "odataType" || + // key === "odataId" || + // key === "eTag" || + // key === "odataEditLink" || + // key.indexOf("@odata.type") > 0 + // ) { + // continue; + // } + // (filteredEntity as any)[key] = entity[key]; + // } + + // resultWithMetaData.push(filteredEntity); + // } + // (responseBody as any).value = resultWithMetaData; + // break; + // } + // } + // return responseBody; + // } + + private getOdataAnnotationUrlPrefix( + tableContext: TableStorageContext, + account: string + ): string { + // TODO: Get protocol, host and port from Azurite server instance let protocol = "http"; - let host = - DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; - - if (tableCtx.request !== undefined) { - host = tableCtx.request.getHeader("host") as string; - protocol = tableCtx.request.getProtocol() as string; - } - - const resultWithMetaData: { [propertyName: string]: any }[] = []; - const responseBody: { [propertyName: string]: any } = {}; - - switch (accept) { - case MINIMAL_METADATA_ACCEPT: { - // Add odata.metadata - (responseBody as any)["odata.metadata"] = - `${protocol}://${host}/` + queryResult[0].odataMetadata; - for (const entity of queryResult) { - const filteredEntity = {}; - for (const key of Object.keys(entity)) { - // Only need metadata and properties' odata type - if ( - key === "odataMetadata" || - key === "odataType" || - key === "odataId" || - key === "eTag" || - key === "odataEditLink" - ) { - continue; - } - // Also add odataType to each field - (filteredEntity as any)[key] = entity[key]; - } - - resultWithMetaData.push(filteredEntity); - } - (responseBody as any).value = resultWithMetaData; - break; - } - case FULL_METADATA_ACCEPT: { - // Add odata.metadata - (responseBody as any)["odata.metadata"] = queryResult[0].odataMetadata; - for (const entity of queryResult) { - const filteredEntity = {}; - for (const key of Object.keys(entity)) { - // Remove odataMetadata of each entity - if (key === "odataMetadata") { - continue; - } - (filteredEntity as any)[key] = entity[key]; - } - - // Add Timestamp@odata.type - (filteredEntity as any)["Timestamp@odata.type"] = "Edm.DateTime"; - - // Solve the name inconsistency of the response and entity - (filteredEntity as any)[ - "odata.type" - ] = (filteredEntity as any).odataType; - delete (filteredEntity as any).odataType; - - (filteredEntity as any)["odata.id"] = - `${protocol}://${host}/` + (filteredEntity as any).odataId; - delete (filteredEntity as any).odataId; - - (filteredEntity as any)["odata.etag"] = (filteredEntity as any).eTag; - delete (filteredEntity as any).eTag; - - (filteredEntity as any)[ - "odata.editLink" - ] = (filteredEntity as any).odataEditLink; - delete (filteredEntity as any).odataEditLink; - - // Add processed entity back - resultWithMetaData.push(filteredEntity); - } - (responseBody as any).value = resultWithMetaData; - break; - } - default: { - for (const entity of queryResult) { - const filteredEntity = {}; - for (const key of Object.keys(entity)) { - // Don't need metadata and properties' odata type - if ( - key === "odataMetadata" || - key === "odataType" || - key === "odataId" || - key === "eTag" || - key === "odataEditLink" || - key.indexOf("@odata.type") > 0 - ) { - continue; - } - (filteredEntity as any)[key] = entity[key]; - } - - resultWithMetaData.push(filteredEntity); - } - (responseBody as any).value = resultWithMetaData; - break; - } + let host = `${DEFAULT_TABLE_SERVER_HOST_NAME}:${DEFAULT_TABLE_LISTENING_PORT}/${account}`; + if (tableContext.request !== undefined) { + host = `${tableContext.request.getHeader("host")}/${account}` || host; + protocol = tableContext.request.getProtocol(); + } + return `${protocol}://${host}`; + } + + private getAndCheckPayloadFormat( + context: TableStorageContext, + formatParameter?: string + ): string { + let format = context.request!.getHeader(HeaderConstants.ACCEPT); + + if (formatParameter === undefined) { + formatParameter = context.request!.getQuery("$format"); + } + + if (format === XML_METADATA) { + format = XML_METADATA; + } + + if (typeof formatParameter === "string") { + format = formatParameter; } - return responseBody; + + if (format === "application/json") { + format = MINIMAL_METADATA_ACCEPT; + } + + if ( + format !== NO_METADATA_ACCEPT && + format !== MINIMAL_METADATA_ACCEPT && + format !== FULL_METADATA_ACCEPT + ) { + throw StorageErrorFactory.getAtomFormatNotSupported(context); + } + + return format; + } + + private getAndCheckPreferHeader( + context: TableStorageContext + ): string | undefined { + const prefer = context.request!.getHeader(HeaderConstants.PREFER); + return prefer; + } + + private getAndCheckAccountName(context: TableStorageContext): string { + const account = context.account; + if (account === undefined) { + throw StorageErrorFactory.getAccountNameEmpty(context); + } + return account; + } + + private getAndCheckTableName(context: TableStorageContext): string { + const table = context.tableName; + if (table === undefined) { + throw StorageErrorFactory.getTableNameEmpty(context); + } + return table; + } + + private getAndCheckPartitionKey(context: TableStorageContext): string { + const partitionKey = context.partitionKey; + if (partitionKey === undefined) { + throw StorageErrorFactory.getTableNameEmpty(context); + } + return partitionKey; + } + + private getAndCheckRowKey(context: TableStorageContext): string { + const rowKey = context.rowKey; + if (rowKey === undefined) { + throw StorageErrorFactory.getTableNameEmpty(context); + } + return rowKey; + } + + private updateResponseAccept( + context: TableStorageContext, + accept?: string + ): TableStorageContext { + if (accept !== undefined) { + context.response!.setContentType(accept); + } + return context; + } + + private updateResponsePrefer( + response: IPartialResponsePreferProperties, + context: TableStorageContext + ): IPartialResponsePreferProperties { + const prefer = context.request!.getHeader(HeaderConstants.PREFER); + if (prefer === RETURN_NO_CONTENT) { + response.statusCode = 204; + response.preferenceApplied = RETURN_NO_CONTENT; + } + if (prefer === RETURN_CONTENT || prefer === undefined) { + response.statusCode = 201; + response.preferenceApplied = RETURN_CONTENT; + } + return response; } } diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index 481ed5f0a..53d0ce95f 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -68,16 +68,19 @@ export function tableStorageContextMiddleware( requestID ); - const [account, tableSection] = extractStoragePartsFromPath( + // tslint:disable-next-line: prefer-const + let [account, tableSection] = extractStoragePartsFromPath( req.hostname, req.path ); + const isGet = req.method.toUpperCase() === "GET"; + // Candidate tableSection // undefined - Set Table Service Properties // Tables - Create Tables, Query Tables - // Tables('mytable') - Delete Tables - // mytable - Get/Set Table ACL, Insert Entity + // Tables('mytable') - Delete Tables, Query Entities + // mytable - Get/Set Table ACL, Insert Entity, Query Entities // mytable(PartitionKey='',RowKey='') - // Query Entities, Update Entity, Merge Entity, Delete Entity // mytable() - Query Entities @@ -94,9 +97,19 @@ export function tableStorageContextMiddleware( ) { // Tables('mytable') tableContext.tableName = tableSection.substring(8, tableSection.length - 2); + + // Workaround for query entity + if (isGet) { + tableSection = `${tableContext.tableName}()`; + } } else if (!tableSection.includes("(") && !tableSection.includes(")")) { // mytable tableContext.tableName = tableSection; + + // Workaround for query entity + if (isGet) { + tableSection = `${tableContext.tableName}()`; + } } else if ( tableSection.includes("(") && tableSection.includes(")") && @@ -125,6 +138,7 @@ export function tableStorageContextMiddleware( tableSection.includes(")") && tableSection.indexOf(")") - tableSection.indexOf("(") === 1 ) { + // mytable() tableContext.tableName = tableSection.substr(0, tableSection.indexOf("(")); } else { logger.error( @@ -150,7 +164,7 @@ export function tableStorageContextMiddleware( tableSection !== undefined ? `/${tableSection}` : "/"; logger.info( - `tableStorageContextMiddleware: Account=${account} tableName=${tableSection}}`, + `tableStorageContextMiddleware: Account=${account} tableName=${tableContext.tableName}`, requestID ); next(); diff --git a/src/table/persistence/ITableMetadataStore.ts b/src/table/persistence/ITableMetadataStore.ts index daece2058..b86be2132 100644 --- a/src/table/persistence/ITableMetadataStore.ts +++ b/src/table/persistence/ITableMetadataStore.ts @@ -2,86 +2,92 @@ import * as Models from "../generated/artifacts/models"; import Context from "../generated/Context"; // Since the host name may change, we don't store host in {@code odatametadata, odatatid} -interface ITtableAdditionalProperties { - tableAcl?: Models.SignedIdentifier[]; - account: string; - tableName: string; +export interface IOdataAnnotations { + odatametadata: string; + odatatype: string; + odataid: string; + odataeditLink: string; +} + +export interface IOdataAnnotationsOptional { odatametadata?: string; odatatype?: string; odataid?: string; odataeditLink?: string; } +interface ITable { + tableAcl?: Models.SignedIdentifier[]; + account: string; + table: string; +} + +export type Table = ITable & IOdataAnnotationsOptional; + export interface IEntity { PartitionKey: string; RowKey: string; eTag: string; lastModifiedTime: Date; properties: { - [propertyName: string]: string | number; + [propertyName: string]: string | number | boolean | null; }; - odataMetadata: string; - odataType: string; - odataId: string; - odataEditLink: string; } -export type TableModel = ITtableAdditionalProperties; +export type Entity = IEntity & IOdataAnnotationsOptional; export default interface ITableMetadataStore { + createTable(context: Context, tableModel: Table): Promise; queryTable( context: Context, - accountName: string - ): Promise; - createTable(context: Context, table: TableModel): Promise; - deleteTable( - context: Context, - tableName: string, - accountName: string - ): Promise; + account: string, + top?: number, + nextTable?: string + ): Promise<[Table[], string | undefined]>; + deleteTable(context: Context, table: string, account: string): Promise; queryTableEntities( context: Context, - accountName: string, + account: string, table: string, - queryOptions: Models.QueryOptions - ): Promise<{ [propertyName: string]: any }[]>; + queryOptions: Models.QueryOptions, + nextPartitionKey?: string, + nextRowKey?: string + ): Promise<[Entity[], string | undefined, string | undefined]>; queryTableEntitiesWithPartitionAndRowKey( context: Context, table: string, - accountName: string, + account: string, partitionKey: string, rowKey: string - ): Promise; - updateTableEntity( + ): Promise; + insertOrUpdateTableEntity( context: Context, - tableName: string, + table: string, account: string, - entity: IEntity, - eatg: string - ): Promise; - mergeTableEntity( + entity: Entity, + ifMatch?: string + ): Promise; + insertOrMergeTableEntity( context: Context, - tableName: string, + table: string, account: string, - entity: IEntity, - etag: string, - partitionKey: string, - rowKey: string - ): Promise; + entity: Entity, + ifMatch?: string + ): Promise; deleteTableEntity( context: Context, - tableName: string, - accountName: string, + table: string, + account: string, partitionKey: string, rowKey: string, etag: string ): Promise; insertTableEntity( context: Context, - tableName: string, + table: string, account: string, - entity: IEntity - ): Promise; + entity: Entity + ): Promise; getTableAccessPolicy( context: Context, table: string, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index d47d83f7b..505d2f23d 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -1,17 +1,18 @@ import { stat } from "fs"; import Loki from "lokijs"; -import { newEtag } from "../../common/utils/utils"; + import NotImplementedError from "../errors/NotImplementedError"; import StorageErrorFactory from "../errors/StorageErrorFactory"; import * as Models from "../generated/artifacts/models"; import Context from "../generated/Context"; -import { IEntity, TableModel } from "../persistence/ITableMetadataStore"; -import { SUPPORTED_QUERY_OPERATOR } from "../utils/constants"; +import { Entity, Table } from "../persistence/ITableMetadataStore"; +import { ODATA_TYPE, QUERY_RESULT_MAX_NUM } from "../utils/constants"; +import { getTimestampString } from "../utils/utils"; import ITableMetadataStore from "./ITableMetadataStore"; export default class LokiTableMetadataStore implements ITableMetadataStore { private readonly db: Loki; - private readonly TABLE_COLLECTION = "$TABLE_COLLECTION$"; + private readonly TABLES_COLLECTION = "$TABLES_COLLECTION$"; private initialized: boolean = false; private closed: boolean = false; @@ -22,6 +23,61 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { }); } + public async init(): Promise { + await new Promise((resolve, reject) => { + stat(this.lokiDBPath, (statError, stats) => { + if (!statError) { + this.db.loadDatabase({}, (dbError) => { + if (dbError) { + reject(dbError); + } else { + resolve(); + } + }); + } else { + // when DB file doesn't exist, ignore the error because following will re-create the file + resolve(); + } + }); + }); + + // Create tables collection if not exists + if (this.db.getCollection(this.TABLES_COLLECTION) === null) { + this.db.addCollection(this.TABLES_COLLECTION, { + // Optimization for indexing and searching + // https://rawgit.com/techfort/LokiJS/master/jsdoc/tutorial-Indexing%20and%20Query%20performance.html + indices: ["account", "table"] + }); // Optimize for find operation + } + + await new Promise((resolve, reject) => { + this.db.saveDatabase((err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + + this.initialized = true; + this.closed = false; + } + + public async close(): Promise { + await new Promise((resolve, reject) => { + this.db.close((err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + + this.closed = true; + } + public isInitialized(): boolean { return this.initialized; } @@ -30,235 +86,406 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { return this.closed; } - public async createTable(context: Context, table: TableModel): Promise { + public async createTable(context: Context, tableModel: Table): Promise { // Check for table entry in the table registry collection - const coll = this.db.getCollection(this.TABLE_COLLECTION); + const coll = this.db.getCollection(this.TABLES_COLLECTION); const doc = coll.findOne({ - account: table.account, - name: table.tableName + account: tableModel.account, + table: tableModel.table }); // If the metadata exists, we will throw getTableAlreadyExists error if (doc) { throw StorageErrorFactory.getTableAlreadyExists(context); } - coll.insert(table); + + coll.insert(tableModel); // now we create the collection to represent the table using a unique string - const uniqueTableName = this.getUniqueTableCollectionName( - table.account, - table.tableName + const tableCollectionName = this.getTableCollectionName( + tableModel.account, + tableModel.table ); - const extentColl = this.db.getCollection(uniqueTableName); + const extentColl = this.db.getCollection(tableCollectionName); if (extentColl) { - throw StorageErrorFactory.getTableAlreadyExists(context); + this.db.removeCollection(tableCollectionName); } - this.db.addCollection(uniqueTableName, { + this.db.addCollection(tableCollectionName, { // Optimization for indexing and searching // https://rawgit.com/techfort/LokiJS/master/jsdoc/tutorial-Indexing%20and%20Query%20performance.html indices: ["PartitionKey", "RowKey"] }); // Optimize for find operation } + public async deleteTable( + context: Context, + table: string, + account: string + ): Promise { + // remove table reference from collection registry + const coll = this.db.getCollection(this.TABLES_COLLECTION); + const doc = coll.findOne({ + account, + table + }); + if (doc) { + coll.remove(doc); + } else { + throw StorageErrorFactory.getTableNotFound(context); + } + + const tableCollectionName = this.getTableCollectionName(account, table); + const tableEntityCollection = this.db.getCollection(tableCollectionName); + if (tableEntityCollection) { + this.db.removeCollection(tableCollectionName); + } + } + + public async queryTable( + context: Context, + account: string, + top: number = 1000, + nextTable?: string + ): Promise<[Table[], string | undefined]> { + const coll = this.db.getCollection(this.TABLES_COLLECTION); + + const filter = { account } as any; + if (nextTable) { + filter.table = { $gte: nextTable }; + } + + const docList = coll + .chain() + .find(filter) + .simplesort("table") + .limit(top + 1) + .data(); + + let nextTableName; + if (docList.length > top) { + const tail = docList.pop(); + nextTableName = tail.table; + } + + if (!docList) { + throw StorageErrorFactory.getEntityNotFound(context); + } + + return [docList, nextTableName]; + } + public async insertTableEntity( context: Context, - tableName: string, + table: string, account: string, - entity: IEntity - ): Promise { - const tableColl = this.db.getCollection( - this.getUniqueTableCollectionName(account, tableName) + entity: Entity + ): Promise { + const tablesCollection = this.db.getCollection(this.TABLES_COLLECTION); + const tableDocument = tablesCollection.findOne({ + account, + table + }); + if (!tableDocument) { + throw StorageErrorFactory.getTableNotExist(context); + } + + const tableEntityCollection = this.db.getCollection( + this.getTableCollectionName(account, table) ); - if (!tableColl) { + if (!tableEntityCollection) { throw StorageErrorFactory.getTableNotExist(context); } - const doc = tableColl.findOne({ + const doc = tableEntityCollection.findOne({ PartitionKey: entity.PartitionKey, RowKey: entity.RowKey }); - if (doc) { throw StorageErrorFactory.getEntityAlreadyExist(context); } - tableColl.insert(entity); - return; + entity.properties.Timestamp = getTimestampString(entity.lastModifiedTime); + entity.properties["Timestamp@odata.type"] = "Edm.DateTime"; + + tableEntityCollection.insert(entity); + return entity; } - public async queryTable( + public async insertOrUpdateTableEntity( context: Context, - accountName: string - ): Promise { - const coll = this.db.getCollection(this.TABLE_COLLECTION); - const docList = coll.find({ account: accountName }); - - if (!docList) { - throw StorageErrorFactory.getEntityNotFound(context); + table: string, + account: string, + entity: Entity, + ifMatch?: string + ): Promise { + if (ifMatch === undefined) { + // Upsert + const existingEntity = await this.queryTableEntitiesWithPartitionAndRowKey( + context, + table, + account, + entity.PartitionKey, + entity.RowKey + ); + + if (existingEntity) { + // Update + return this.updateTableEntity(context, table, account, entity, ifMatch); + } else { + // Insert + return this.insertTableEntity(context, table, account, entity); + } + } else { + // Update + return this.updateTableEntity(context, table, account, entity, ifMatch); } - let response: Models.TableResponseProperties[] = []; + // const tablesCollection = this.db.getCollection(this.TABLES_COLLECTION); + // const tableDocument = tablesCollection.findOne({ + // account, + // table + // }); + // if (!tableDocument) { + // throw StorageErrorFactory.getTableNotExist(context); + // } + + // const tableEntityCollection = this.db.getCollection( + // this.getTableCollectionName(account, table) + // ); + // if (!tableEntityCollection) { + // throw StorageErrorFactory.getTableNotExist(context); + // } + + // const doc = tableEntityCollection.findOne({ + // PartitionKey: entity.PartitionKey, + // RowKey: entity.RowKey + // }) as Entity; + + // if (!doc) { + // throw StorageErrorFactory.getEntityNotExist(context); + // } else { + // // Test if etag value is valid + // if (ifMatch === "*" || doc.eTag === ifMatch) { + // tableEntityCollection.remove(doc); + + // entity.properties.Timestamp = getTimestampString( + // entity.lastModifiedTime + // ); + // entity.properties["Timestamp@odata.type"] = "Edm.DateTime"; + + // tableEntityCollection.insert(entity); + // return; + // } + // } + + // throw StorageErrorFactory.getPreconditionFailed(context); + } - if (docList.length > 0) { - response = docList.map(item => { - return { - odatatype: item.odatatype, - odataid: item.odataid, - odataeditLink: item.odataeditLink, - tableName: item.tableName - }; - }); + public async insertOrMergeTableEntity( + context: Context, + table: string, + account: string, + entity: Entity, + ifMatch?: string + ): Promise { + if (ifMatch === undefined) { + // Upsert + const existingEntity = await this.queryTableEntitiesWithPartitionAndRowKey( + context, + table, + account, + entity.PartitionKey, + entity.RowKey + ); + + if (existingEntity) { + // Merge + return this.mergeTableEntity(context, table, account, entity, ifMatch); + } else { + // Insert + return this.insertTableEntity(context, table, account, entity); + } + } else { + // Merge + return this.mergeTableEntity(context, table, account, entity, ifMatch); } - return response; + // const tablesCollection = this.db.getCollection(this.TABLES_COLLECTION); + // const tableDocument = tablesCollection.findOne({ + // account, + // table + // }); + // if (!tableDocument) { + // throw StorageErrorFactory.getTableNotExist(context); + // } + + // const tableEntityCollection = this.db.getCollection( + // this.getTableCollectionName(account, table) + // ); + // if (!tableEntityCollection) { + // throw StorageErrorFactory.getTableNotExist(context); + // } + + // const doc = tableEntityCollection.findOne({ + // PartitionKey: entity.PartitionKey, + // RowKey: entity.RowKey + // }) as Entity; + + // if (!doc) { + // throw StorageErrorFactory.getEntityNotExist(context); + // } else { + // // Test if etag value is valid + // if (ifMatch === "*" || doc.eTag === ifMatch) { + // const mergedDEntity: Entity = { + // ...doc, + // ...entity, + // properties: { + // // TODO: Validate incoming odata types + // ...doc.properties, + // ...entity.properties, + // Timestamp: getTimestampString(entity.lastModifiedTime), + // "Timestamp@odata.type": "Edm.DateTime" + // }, + // lastModifiedTime: context.startTime! + // }; + // tableEntityCollection.remove(doc); + // tableEntityCollection.insert(mergedDEntity); + // return mergedDEntity; + // } + // } + // throw StorageErrorFactory.getPreconditionFailed(context); } - public async deleteTable( + public async deleteTableEntity( context: Context, - name: string, - accountName: string + table: string, + account: string, + partitionKey: string, + rowKey: string, + etag: string ): Promise { - const uniqueTableName = this.getUniqueTableCollectionName( - accountName, - name - ); - const tableColl = this.db.getCollection(uniqueTableName); - // delete the collection / table - if (tableColl != null) { - this.db.removeCollection(uniqueTableName); - } else { - throw StorageErrorFactory.getTableNotFound(context); - } - // remove table reference from collection registry - const coll = this.db.getCollection(this.TABLE_COLLECTION); - const doc = coll.findOne({ - account: accountName, - tableName: name + const tablesCollection = this.db.getCollection(this.TABLES_COLLECTION); + const tableDocument = tablesCollection.findOne({ + account, + table }); - if (doc != null) { - coll.remove(doc); - } else { - throw StorageErrorFactory.getTableNotFound(context); + if (!tableDocument) { + throw StorageErrorFactory.getTableNotExist(context); } - } - public async queryTableEntities( - context: Context, - accountName: string, - tableName: string, - queryOptions: Models.QueryOptions - ): Promise<{ [propertyName: string]: any }[]> { - const tableColl = this.db.getCollection( - this.getUniqueTableCollectionName(accountName, tableName) + const tableEntityCollection = this.db.getCollection( + this.getTableCollectionName(account, table) ); + if (!tableEntityCollection) { + throw StorageErrorFactory.getTableNotExist(context); + } - // Split parameters for filter - const filters = queryOptions.filter!.split("and"); - const filterJson = {}; - for (let condition of filters) { - condition = condition.trim(); - const length = condition.length; - - // Remove wrapping parentheses - if (condition[0] === "(" && condition[length - 1] === ")") { - condition = condition.substr(1, length - 2); - } + if (partitionKey !== undefined && rowKey !== undefined) { + const doc = tableEntityCollection.findOne({ + PartitionKey: partitionKey, + RowKey: rowKey + }) as Entity; - const comps = condition.split(" "); - if (comps.length !== 3) { - throw StorageErrorFactory.getQueryConditionInvalid(context); + if (!doc) { + throw StorageErrorFactory.getEntityNotFound(context); + } else { + if (etag !== "*" && doc.eTag !== etag) { + throw StorageErrorFactory.getPreconditionFailed(context); + } } - let operator = comps[1]; - const firstParam = "properties." + comps[0]; - let secondParam = comps[2]; + tableEntityCollection.remove(doc); + return; + } - if (SUPPORTED_QUERY_OPERATOR.indexOf(operator) >= 0) { - const rightExpressionJSON = {}; + throw StorageErrorFactory.getPropertiesNeedValue(context); + } - // Fix inconsistency with azure table query operator - // and lokijs query operator - if (operator === "ge") { - operator = "gte"; - } + public async queryTableEntities( + context: Context, + account: string, + table: string, + queryOptions: Models.QueryOptions, + nextPartitionKey?: string, + nextRowKey?: string + ): Promise<[Entity[], string | undefined, string | undefined]> { + const tablesCollection = this.db.getCollection(this.TABLES_COLLECTION); + const tableDocument = tablesCollection.findOne({ + account, + table + }); + if (!tableDocument) { + throw StorageErrorFactory.getTableNotExist(context); + } - if (operator === "le") { - operator = "lte"; - } + const tableEntityCollection = this.db.getCollection( + this.getTableCollectionName(account, table) + ); + if (!tableEntityCollection) { + throw StorageErrorFactory.getTableNotExist(context); + } - operator = "$" + operator; - secondParam = this.convertQueryParameters(secondParam, context); + let queryWhere; + try { + queryWhere = this.generateQueryEntityWhereFunction(queryOptions.filter); + } catch (e) { + throw StorageErrorFactory.getQueryConditionInvalid(context); + } - (rightExpressionJSON as any)[operator] = secondParam; - (filterJson as any)[firstParam] = rightExpressionJSON; - } else { - throw StorageErrorFactory.getQueryConditionInvalid(context); - } + const segmentFilter = {} as any; + if (nextPartitionKey) { + segmentFilter.PartitionKey = { $gte: nextPartitionKey }; + } + if (nextRowKey) { + segmentFilter.RowKey = { $gte: nextRowKey }; } - // Query Result - const result = tableColl.find(filterJson); - if (result.length === 0) { - return result; - } - - let selectedResult = result; - - // Only return selected fields - if (queryOptions.select !== undefined) { - const selectedFieldsResult = []; - const selectedFields = queryOptions.select.split(","); - - // Iterate all entities and get selected fields - for (const entity of result) { - // Check if the selected result has exceeded the top limits - const entitySelectedFieldResult = {}; - (entitySelectedFieldResult as any).PartitionKey = entity.PartitionKey; - (entitySelectedFieldResult as any).RowKey = entity.RowKey; - (entitySelectedFieldResult as any).odataMetadata = entity.odataMetadata; - (entitySelectedFieldResult as any).odataType = entity.odataType; - (entitySelectedFieldResult as any).odataId = entity.odataId; - (entitySelectedFieldResult as any).odataEditLink = entity.odataEditLink; - (entitySelectedFieldResult as any).eTag = entity.eTag; - (entitySelectedFieldResult as any).Timestamp = entity.lastModifiedTime; - - for (let field of selectedFields) { - field = field.trim(); - const keys = field.split("."); - let val = entity.properties; - for (const key of keys) { - val = val[key]; + const maxResults = queryOptions.top || QUERY_RESULT_MAX_NUM; + + const result = tableEntityCollection + .chain() + .find(segmentFilter) + .where(queryWhere) + .sort((obj1, obj2) => { + if (obj1.PartitionKey > obj2.PartitionKey) { + return 1; + } else if (obj1.PartitionKey === obj2.PartitionKey) { + if (obj1.RowKey > obj2.RowKey) { + return 1; + } else if (obj1.RowKey === obj2.RowKey) { + return 0; + } else { + return -1; } - (entitySelectedFieldResult as any)[field] = val; - (entitySelectedFieldResult as any)[ - field + "@odata.type" - ] = this.getODataType(val); + } else { + return -1; } + }) + .limit(maxResults + 1) + .data(); - // Add to result - selectedFieldsResult.push(entitySelectedFieldResult); - } + let nextPartitionKeyResponse; + let nextRowKeyResponse; - selectedResult = selectedFieldsResult; + if (result.length > maxResults) { + const tail = result.pop(); + nextPartitionKeyResponse = tail.PartitionKey; + nextRowKeyResponse = tail.RowKey; } - if (queryOptions.top !== undefined) { - selectedResult = selectedResult.slice(0, queryOptions.top!); - } - - return selectedResult; + return [result, nextPartitionKeyResponse, nextRowKeyResponse]; } public async queryTableEntitiesWithPartitionAndRowKey( context: Context, - tableName: string, - accountName: string, + table: string, + account: string, partitionKey: string, rowKey: string - ): Promise { + ): Promise { const tableColl = this.db.getCollection( - this.getUniqueTableCollectionName(accountName, tableName) + this.getTableCollectionName(account, table) ); // Throw error, if table not exists @@ -270,251 +497,264 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { const requestedDoc = tableColl.findOne({ PartitionKey: partitionKey, RowKey: rowKey - }) as IEntity; + }) as Entity; return requestedDoc; } - public async updateTableEntity( + public async getTableAccessPolicy( + context: Context, + table: string + ): Promise { + // TODO + throw new NotImplementedError(); + } + + public async setTableAccessPolicy( context: Context, - tableName: string, + table: string + ): Promise { + // TODO + throw new NotImplementedError(); + } + + private async updateTableEntity( + context: Context, + table: string, account: string, - entity: IEntity, - etag: string - ): Promise { - const tableColl = this.db.getCollection( - this.getUniqueTableCollectionName(account, tableName) - ); + entity: Entity, + ifMatch?: string + ): Promise { + const tablesCollection = this.db.getCollection(this.TABLES_COLLECTION); + const tableDocument = tablesCollection.findOne({ + account, + table + }); + if (!tableDocument) { + throw StorageErrorFactory.getTableNotExist(context); + } - // Throw error, if table not exists - if (!tableColl) { + const tableEntityCollection = this.db.getCollection( + this.getTableCollectionName(account, table) + ); + if (!tableEntityCollection) { throw StorageErrorFactory.getTableNotExist(context); } - // Get Current Doc - const currentDoc = tableColl.findOne({ + const doc = tableEntityCollection.findOne({ PartitionKey: entity.PartitionKey, RowKey: entity.RowKey - }) as IEntity; + }) as Entity; - // Throw error, if doc does not exist - if (!currentDoc) { + if (!doc) { throw StorageErrorFactory.getEntityNotExist(context); - } else { - // Test if etag value is valid - if (etag === "*" || currentDoc.eTag === etag) { - tableColl.remove(currentDoc); - tableColl.insert(entity); - return; - } + } + + // Test if etag value is valid + if (ifMatch === undefined || ifMatch === "*" || doc.eTag === ifMatch) { + tableEntityCollection.remove(doc); + + entity.properties.Timestamp = getTimestampString(entity.lastModifiedTime); + entity.properties["Timestamp@odata.type"] = "Edm.DateTime"; + + tableEntityCollection.insert(entity); + return entity; } throw StorageErrorFactory.getPreconditionFailed(context); } - public async mergeTableEntity( + private async mergeTableEntity( context: Context, - tableName: string, + table: string, account: string, - entity: IEntity, - etag: string - ): Promise { - const tableColl = this.db.getCollection( - this.getUniqueTableCollectionName(account, tableName) - ); + entity: Entity, + ifMatch?: string + ): Promise { + const tablesCollection = this.db.getCollection(this.TABLES_COLLECTION); + const tableDocument = tablesCollection.findOne({ + account, + table + }); + if (!tableDocument) { + throw StorageErrorFactory.getTableNotExist(context); + } - // Throw error, if table not exists - if (!tableColl) { + const tableEntityCollection = this.db.getCollection( + this.getTableCollectionName(account, table) + ); + if (!tableEntityCollection) { throw StorageErrorFactory.getTableNotExist(context); } - // Get Current Doc - const currentDoc = tableColl.findOne({ + const doc = tableEntityCollection.findOne({ PartitionKey: entity.PartitionKey, RowKey: entity.RowKey - }) as IEntity; + }) as Entity; - // Throw error, if doc does not exist - if (!currentDoc) { + if (!doc) { throw StorageErrorFactory.getEntityNotExist(context); - } else { - // Test if etag value is valid - if (etag === "*" || currentDoc.eTag === etag) { - const mergedDoc = { - ...currentDoc, - ...entity - }; - mergedDoc.eTag = newEtag(); - tableColl.update(mergedDoc); - return mergedDoc.eTag; - } } - throw StorageErrorFactory.getPreconditionFailed(context); - } - public async deleteTableEntity( - context: Context, - tableName: string, - accountName: string, - partitionKey: string, - rowKey: string, - etag: string - ): Promise { - const tableColl = this.db.getCollection( - this.getUniqueTableCollectionName(accountName, tableName) - ); - if (!tableColl) { - throw StorageErrorFactory.getTableNotExist(context); - } - - if (partitionKey !== undefined && rowKey !== undefined) { - const doc = tableColl.findOne({ - PartitionKey: partitionKey, - RowKey: rowKey - }) as IEntity; - - if (!doc) { - throw StorageErrorFactory.getEntityNotFound(context); - } else { - if (etag !== "*" && doc.eTag !== etag) { - throw StorageErrorFactory.getPreconditionFailed(context); + if (ifMatch === undefined || ifMatch === "*" || doc.eTag === ifMatch) { + const mergedDEntity: Entity = { + ...doc, + ...entity, + properties: { + ...doc.properties + // ...entity.properties } - } - tableColl.remove(doc); - return; - } + }; - throw StorageErrorFactory.getPropertiesNeedValue(context); - } - - public async getTableAccessPolicy( - context: Context, - table: string - ): Promise { - // TODO - throw new NotImplementedError(); - } + // Merge inner properties + for (const key in entity.properties) { + if (Object.prototype.hasOwnProperty.call(entity.properties, key)) { + if (key.endsWith(ODATA_TYPE)) { + continue; + } - public async setTableAccessPolicy( - context: Context, - table: string - ): Promise { - // TODO - throw new NotImplementedError(); - } + const value = entity.properties[key]; + mergedDEntity.properties[key] = value; - public async init(): Promise { - await new Promise((resolve, reject) => { - stat(this.lokiDBPath, (statError, stats) => { - if (!statError) { - this.db.loadDatabase({}, dbError => { - if (dbError) { - reject(dbError); - } else { - resolve(); - } - }); - } else { - // when DB file doesn't exist, ignore the error because following will re-create the file - resolve(); + if (entity.properties[`${key}${ODATA_TYPE}`] !== undefined) { + mergedDEntity.properties[`${key}${ODATA_TYPE}`] = + entity.properties[`${key}${ODATA_TYPE}`]; + } else { + delete mergedDEntity.properties[`${key}${ODATA_TYPE}`]; + } } - }); - }); + } - // Create tables collection if not exists - if (this.db.getCollection(this.TABLE_COLLECTION) === null) { - this.db.addCollection(this.TABLE_COLLECTION, { - // Optimization for indexing and searching - // https://rawgit.com/techfort/LokiJS/master/jsdoc/tutorial-Indexing%20and%20Query%20performance.html - indices: ["accountName", "name"] - }); // Optimize for find operation + tableEntityCollection.update(mergedDEntity); + return mergedDEntity; + } else { + throw StorageErrorFactory.getPreconditionFailed(context); } - - await new Promise((resolve, reject) => { - this.db.saveDatabase(err => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); - - this.initialized = true; - this.closed = false; } - public async close(): Promise { - await new Promise((resolve, reject) => { - this.db.close(err => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); - - this.closed = true; + private getTableCollectionName(account: string, table: string): string { + return `${account}$${table}`; } - private getUniqueTableCollectionName( - accountName: string, - tableName: string - ): string { - return `${accountName}$${tableName}`; - } - - private convertQueryParameters(param: string, context: Context): any { - const length = param.length; - if (param[0] === "'" && param[length - 1] === "'") { - // Param is of type string - // Convert middle '' to ' - const idx = param.indexOf("''"); - if (idx > 0) { - param = param.substr(0, idx) + param.substr(idx + 1, length); - } - return param.substr(1, param.length - 2); - } - - if (param === "true" || param === "false") { - // Param is of type boolean - return param === "true"; + /** + * Azurite V2 query entities implementation as temporary workaround before new refactored implementation of querying. + * TODO: Handle query types + * + * @param query Query Enties $query string. + */ + private generateQueryEntityWhereFunction( + query: string | undefined + ): (entity: Entity) => boolean { + if (query === undefined) { + return () => true; } - const floatVal = parseFloat(param); - const intVal = parseInt(param, 10); - - if (!isNaN(floatVal)) { - if (intVal === floatVal) { - return intVal; - } else { - return floatVal; + const filter = query + // ignoring these query keywords since we compare simply on a string-level + // .replace(/\bbinary\b/g, "") + .replace(/\bguid\b/g, "") + // Escape a single backtick to prevent interpreting the start of a template literal. + .replace(/`/g, "\\`") + // A simple quotation mark is escaped with another one (i.e. ''). + // Since we will evaluate this string we replace simple quotation marks + // indictaing strings with template quotation marks + .replace(/''/g, "@ESCAPEDQUOTE@") + .replace(/'/g, "`") + .replace(/@ESCAPEDQUOTE@/g, `'`) + // Mapping 'TableName' to 'name' which is used internally as attribute name + .replace(/\bTableName\b/g, "name") + // Mapping operators + .replace(/\beq\b/g, "===") + .replace(/\bgt\b/g, ">") + .replace(/\bge\b/g, ">=") + .replace(/\blt\b/g, "<") + .replace(/\ble\b/g, "<=") + .replace(/\bne\b/g, "!==") + .replace(/\band\b/g, "&&") + .replace(/\bor\b/g, "||") + .replace(/\(/g, " ( ") + .replace(/\)/g, " ) ") + .replace(/\bnot\b/g, " ! "); + + // If a token is neither a number, nor a boolean, nor a string enclosed with quotation marks it is an operand. + // Operands are attributes of the object used within the where clause of LokiJS, thus we need to prepend each + // attribute with an object identifier 'item.attribs'. + let transformedQuery = "return ( "; + let isOp = false; + let previousIsOp = false; + const tokens = filter.split(" "); + let counter = -1; + for (let token of tokens) { + counter++; + if (token === "") { + continue; } - } else { - throw StorageErrorFactory.getQueryConditionInvalid(context); - } - } - private getODataType(val: any) { - switch (typeof val) { - case "string": { - return "Edm.String"; - } - case "number": { - if (Number.isInteger(val)) { - return "Edm.Int32"; + previousIsOp = isOp; + isOp = ["===", ">", ">=", "<", "<=", "!=="].includes(token); + + if ( + !token.match(/\b\d+/) && + token !== "true" && + token !== "false" && + !token.includes("`") && + ![ + "===", + ">", + ">=", + "<", + "<=", + "!==", + "&&", + "||", + "!", + "(", + ")" + ].includes(token) + ) { + if (token === "PartitionKey" || token === "RowKey") { + transformedQuery += `item.${token} `; } else { - return "Edm.Float"; + // Datetime compare + if ( + counter + 2 <= tokens.length - 1 && + tokens[counter + 2].startsWith("datetime") + ) { + transformedQuery += `new Date(item.properties.${token}).getTime() `; + } else { + transformedQuery += `item.properties.${token} `; + } } - } - case "boolean": { - return "Edm.Boolean"; + } else { + // Remove "L" from long int + // 2039283L ==> 2039283 + const matchLongInt = token.match(/\b[0-9]*L\b/g); + if ( + previousIsOp && + matchLongInt !== null && + matchLongInt.length === 1 + ) { + token = token.replace(/L\b/g, ""); + } else if (previousIsOp && token.startsWith("datetime")) { + token = token.replace(/\bdatetime\b/g, ""); + token = `new Date(${token}).getTime()`; + } else if ( + previousIsOp && + (token.startsWith("X") || token.startsWith("binary")) + ) { + throw Error("Binary filter is not supported yet."); + } + + transformedQuery += `${token} `; } } + transformedQuery += ")"; - if (val instanceof Date) { - return "Edm.DateTime"; - } + // tslint:disable-next-line: no-console + console.log(query); + // tslint:disable-next-line: no-console + console.log(transformedQuery); + + return new Function("item", transformedQuery) as any; } } diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index 26226f95c..7d99be545 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -25,7 +25,9 @@ export const HeaderConstants = { CONTENT_LENGTH: "content-length", DATE: "date", X_MS_DATE: "x-ms-date", - X_MS_VERSION: "x-ms-version" + X_MS_VERSION: "x-ms-version", + ACCEPT: "accept", + PREFER: "Prefer" }; export const SUPPORTED_QUERY_OPERATOR = ["eq", "gt", "ge", "lt", "le", "ne"]; @@ -33,11 +35,13 @@ export const SUPPORTED_QUERY_OPERATOR = ["eq", "gt", "ge", "lt", "le", "ne"]; export const NO_METADATA_ACCEPT = "application/json;odata=nometadata"; export const MINIMAL_METADATA_ACCEPT = "application/json;odata=minimalmetadata"; export const FULL_METADATA_ACCEPT = "application/json;odata=fullmetadata"; +export const XML_METADATA = "application/atom+xml"; +export const ODATA_TYPE = "@odata.type"; export const RETURN_NO_CONTENT = "return-no-content"; export const RETURN_CONTENT = "return-content"; -export const QUERY_RESULT_MAX_NUM = 0; +export const QUERY_RESULT_MAX_NUM = 1000; export const ValidAPIVersions = [ "2019-12-12", "2019-07-07", diff --git a/src/table/utils/utils.ts b/src/table/utils/utils.ts index 18cc1bda0..498171459 100644 --- a/src/table/utils/utils.ts +++ b/src/table/utils/utils.ts @@ -1,5 +1,220 @@ import StorageErrorFactory from "../errors/StorageErrorFactory"; -import { HeaderConstants } from "./constants"; +import { TableResponseProperties } from "../generated/artifacts/models"; +import { + Entity, + IOdataAnnotations, + IOdataAnnotationsOptional, + Table +} from "../persistence/ITableMetadataStore"; +import { + FULL_METADATA_ACCEPT, + HeaderConstants, + MINIMAL_METADATA_ACCEPT +} from "./constants"; + +export function getTableOdataAnnotationsForRequest( + account: string, + table: string +): IOdataAnnotations { + return getOdataAnnotations(account, "", table); +} + +export function getTableOdataAnnotationsForResponse( + account: string, + table: string, + urlPrefix: string +): IOdataAnnotations { + return getOdataAnnotations(account, urlPrefix, table); +} + +export function updateTableOdataAnnotationsForResponse( + table: Table, + account: string, + urlPrefix: string, + accept?: string +): Table { + const annotation = getTableOdataAnnotationsForResponse( + account, + table.table, + urlPrefix + ); + + if ( + accept && + (accept === MINIMAL_METADATA_ACCEPT || accept === FULL_METADATA_ACCEPT) + ) { + table.odatametadata = annotation.odatametadata; + } + + if (accept && accept === FULL_METADATA_ACCEPT) { + table.odatatype = annotation.odatatype; + table.odataid = annotation.odataid; + table.odataeditLink = annotation.odataeditLink; + } + + return table; +} + +export function getTablePropertiesOdataAnnotationsForResponse( + tableName: string, + account: string, + urlPrefix: string, + accept?: string +): TableResponseProperties { + const table: TableResponseProperties = { + tableName + }; + + const annotation = getTableOdataAnnotationsForResponse( + account, + tableName, + urlPrefix + ); + + if (accept && accept === FULL_METADATA_ACCEPT) { + table.odatatype = annotation.odatatype; + table.odataid = annotation.odataid; + table.odataeditLink = annotation.odataeditLink; + } + + return table; +} + +export function updateTableOptionalOdataAnnotationsForResponse( + tableLike: IOdataAnnotationsOptional, + account: string, + table: string, + urlPrefix: string, + accept?: string +): IOdataAnnotationsOptional { + const annotation = getTableOdataAnnotationsForResponse( + account, + table, + urlPrefix + ); + + if ( + accept && + (accept === MINIMAL_METADATA_ACCEPT || accept === FULL_METADATA_ACCEPT) + ) { + tableLike.odatametadata = annotation.odatametadata; + } + + if (accept && accept === FULL_METADATA_ACCEPT) { + tableLike.odatatype = annotation.odatatype; + tableLike.odataid = annotation.odataid; + tableLike.odataeditLink = annotation.odataeditLink; + } + + return tableLike; +} + +export function getEntityOdataAnnotationsForRequest( + account: string, + table: string, + partitionKey?: string, + rowKey?: string +): IOdataAnnotations { + return getOdataAnnotations(account, "", table, partitionKey, rowKey); +} + +export function getEntityOdataAnnotationsForResponse( + account: string, + table: string, + urlPrefix: string, + partitionKey?: string, + rowKey?: string, + accept?: string +): IOdataAnnotationsOptional { + const annotation = getOdataAnnotations( + account, + urlPrefix, + table, + partitionKey, + rowKey + ); + const response: IOdataAnnotationsOptional = {}; + + if ( + accept && + (accept === MINIMAL_METADATA_ACCEPT || accept === FULL_METADATA_ACCEPT) + ) { + response.odatametadata = annotation.odatametadata; + } + + if (accept && accept === FULL_METADATA_ACCEPT) { + response.odatatype = annotation.odatatype; + response.odataid = annotation.odataid; + response.odataeditLink = annotation.odataeditLink; + } + + return response; +} + +export function updateEntityOdataAnnotationsForResponse( + entity: Entity, + account: string, + table: string, + urlPrefix: string, + accept?: string +): Entity { + const annotation = getOdataAnnotations( + account, + table, + urlPrefix, + entity.PartitionKey, + entity.RowKey + ); + + if ( + accept && + (accept === MINIMAL_METADATA_ACCEPT || accept === FULL_METADATA_ACCEPT) + ) { + entity.odatametadata = annotation.odatametadata; + } + + if (accept && accept === FULL_METADATA_ACCEPT) { + entity.odatatype = annotation.odatatype; + entity.odataid = annotation.odataid; + entity.odataeditLink = annotation.odataeditLink; + } + + return entity; +} + +export function getOdataAnnotations( + account: string, + urlPrefix: string, + table?: string, + partitionKey?: string, + rowKey?: string +): IOdataAnnotations { + const urlPrefixEndWithSlash = urlPrefix.endsWith("/") + ? urlPrefix + : `${urlPrefix}/`; + + if (typeof partitionKey === "string" && partitionKey.length > 0) { + if (typeof rowKey !== "string" || partitionKey.length === 0) { + throw TypeError("PartitionKey and RowKey must provide at the same time."); + } + + return { + odatametadata: `${urlPrefixEndWithSlash}$metadata#${table}`, + odatatype: `${account}.${table}`, + odataid: `${urlPrefixEndWithSlash}${table}(PartitionKey='${partitionKey}',RowKey='${rowKey}')`, + odataeditLink: `${table}(PartitionKey='${partitionKey}',RowKey='${rowKey}')` + }; + } else { + return { + odatametadata: `${urlPrefixEndWithSlash}$metadata#Tables${ + table ? "/@Element" : "" + }`, + odatatype: `${account}.Tables`, + odataid: `${urlPrefixEndWithSlash}Tables('${table}')`, + odataeditLink: `Tables('${table}')` + }; + } +} export function checkApiVersion( inputApiVersion: string, @@ -13,3 +228,7 @@ export function checkApiVersion( }); } } + +export function getTimestampString(date: Date): string { + return date.toISOString().replace("Z", "0000Z"); +} diff --git a/swagger/table.md b/swagger/table.md index 693033ef1..cb1be1fd3 100644 --- a/swagger/table.md +++ b/swagger/table.md @@ -92,4 +92,32 @@ directive: $.post.operationId = "Table_MergeEntityWithMerge" ``` -### TODO: Move Table Batch swagger change here \ No newline at end of file +### Update Query Entity With PartitionKey and RowKey response to file + +```yaml +directive: + - from: swagger-document + where: $["paths"]["/{table}(PartitionKey='{partitionKey}',RowKey='{rowKey}')"].get.responses["200"] + transform: > + $.schema = { + "type": "object", + "format": "file" + }; +``` + +### Update Query Entities response to file + +```yaml +directive: + - from: swagger-document + where: $["paths"]["/{table}()"].get.responses["200"] + transform: > + $.schema = { + "type": "object", + "format": "file" + }; +``` + +### TODO: Move Table Batch swagger change here + +### TODO: Move query entity with partition key and row key change here diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index 5a39d7fca..408536062 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -59,7 +59,7 @@ describe("table APIs test", () => { restoreBuildRequestOptions(tableService); }); - it("createTable, prefer=return-no-content, accept=application/json;odata=minimalmetadata @loki", done => { + it("createTable, prefer=return-no-content, accept=application/json;odata=minimalmetadata @loki", (done) => { /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, thus we workaround this by override request headers to test following 3 OData levels responses. - application/json;odata=nometadata @@ -83,7 +83,7 @@ describe("table APIs test", () => { }); }); - it("createTable, prefer=return-content, accept=application/json;odata=fullmetadata @loki", done => { + it("createTable, prefer=return-content, accept=application/json;odata=fullmetadata @loki", (done) => { /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, thus we workaround this by override request headers to test following 3 OData levels responses. - application/json;odata=nometadata @@ -121,17 +121,17 @@ describe("table APIs test", () => { }); }); - it("createTable, prefer=return-content, accept=application/json;odata=minimalmetadata @loki", done => { + it("createTable, prefer=return-content, accept=application/json;odata=minimalmetadata @loki", (done) => { // TODO done(); }); - it("createTable, prefer=return-content, accept=application/json;odata=nometadata @loki", done => { + it("createTable, prefer=return-content, accept=application/json;odata=nometadata @loki", (done) => { // TODO done(); }); - it("queryTable, accept=application/json;odata=fullmetadata @loki", done => { + it("queryTable, accept=application/json;odata=fullmetadata @loki", (done) => { /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, thus we workaround this by override request headers to test following 3 OData levels responses. - application/json;odata=nometadata @@ -142,8 +142,12 @@ describe("table APIs test", () => { accept: "application/json;odata=fullmetadata" }; - tableService.listTablesSegmented(null as any, (error, result, response) => { - if (!error) { + tableService.listTablesSegmented( + null as any, + { maxResults: 20 }, + (error, result, response) => { + assert.deepStrictEqual(error, null); + assert.equal(response.statusCode, 200); const headers = response.headers!; assert.equal(headers["x-ms-version"], TABLE_API_VERSION); @@ -152,16 +156,17 @@ describe("table APIs test", () => { bodies["odata.metadata"], `${protocol}://${host}:${port}/${accountName}/$metadata#Tables` ); - assert.ok(bodies.TableResponseProperties[0].TableName); - assert.ok(bodies.TableResponseProperties[0]["odata.type"]); - assert.ok(bodies.TableResponseProperties[0]["odata.id"]); - assert.ok(bodies.TableResponseProperties[0]["odata.editLink"]); + assert.ok(bodies.value[0].TableName); + assert.ok(bodies.value[0]["odata.type"]); + assert.ok(bodies.value[0]["odata.id"]); + assert.ok(bodies.value[0]["odata.editLink"]); + + done(); } - done(); - }); + ); }); - it("queryTable, accept=application/json;odata=minimalmetadata @loki", done => { + it("queryTable, accept=application/json;odata=minimalmetadata @loki", (done) => { /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, thus we workaround this by override request headers to test following 3 OData levels responses. - application/json;odata=nometadata @@ -182,13 +187,13 @@ describe("table APIs test", () => { bodies["odata.metadata"], `${protocol}://${host}:${port}/${accountName}/$metadata#Tables` ); - assert.ok(bodies.TableResponseProperties[0].TableName); + assert.ok(bodies.value[0].TableName); } done(); }); }); - it("queryTable, accept=application/json;odata=nometadata @loki", done => { + it("queryTable, accept=application/json;odata=nometadata @loki", (done) => { /* Azure Storage Table SDK doesn't support customize Accept header and Prefer header, thus we workaround this by override request headers to test following 3 OData levels responses. - application/json;odata=nometadata @@ -205,13 +210,13 @@ describe("table APIs test", () => { const headers = response.headers!; assert.equal(headers["x-ms-version"], TABLE_API_VERSION); const bodies = response.body! as any; - assert.ok(bodies.TableResponseProperties[0].TableName); + assert.ok(bodies.value[0].TableName); } done(); }); }); - it("deleteTable that exists, @loki", done => { + it("deleteTable that exists, @loki", (done) => { /* https://docs.microsoft.com/en-us/rest/api/storageservices/delete-table */ @@ -237,7 +242,7 @@ describe("table APIs test", () => { }); }); - it("deleteTable that does not exist, @loki", done => { + it("deleteTable that does not exist, @loki", (done) => { // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-table requestOverride.headers = {}; @@ -251,7 +256,7 @@ describe("table APIs test", () => { }); }); - it("createTable with invalid version, @loki", done => { + it("createTable with invalid version, @loki", (done) => { requestOverride.headers = { [HeaderConstants.X_MS_VERSION]: "invalid" }; tableService.createTable("test", (error, result) => { diff --git a/tests/testutils.ts b/tests/testutils.ts index ff3068aad..dd1e94806 100644 --- a/tests/testutils.ts +++ b/tests/testutils.ts @@ -32,25 +32,25 @@ export function padStart( targetLength: number, padString: string = " " ): string { - if (String.prototype.padStart) { - return currentString.padStart(targetLength, padString); - } - - padString = padString || " "; - if (currentString.length > targetLength) { - return currentString; - } else { - targetLength = targetLength - currentString.length; - if (targetLength > padString.length) { - padString += padString.repeat(targetLength / padString.length); - } - return padString.slice(0, targetLength) + currentString; - } + // if (String.prototype.padStart) { + return currentString.padStart(targetLength, padString); + // } + + // padString = padString || " "; + // if (currentString.length > targetLength) { + // return currentString; + // } else { + // targetLength = targetLength - currentString.length; + // if (targetLength > padString.length) { + // padString += padString.repeat(targetLength / padString.length); + // } + // return padString.slice(0, targetLength) + currentString; + // } } export async function rmRecursive(path: string): Promise { return new Promise((resolve, reject) => { - rimraf(path, err => { + rimraf(path, (err) => { if (err) { resolve(); // TODO: Handle delete errors @@ -95,7 +95,7 @@ export async function bodyToString( } export async function sleep(time: number): Promise { - return new Promise(resolve => { + return new Promise((resolve) => { setTimeout(resolve, time); }); } diff --git a/tslint.json b/tslint.json index 74f2dd55b..626e1cbac 100644 --- a/tslint.json +++ b/tslint.json @@ -11,5 +11,11 @@ "array-type": false }, "rulesDirectory": [], - "linterOptions": {} + "linterOptions": { + "exclude": [ + "src/blob/generated/**/*", + "src/table/generated/**/*", + "src/queue/generated/**/*" + ] + } } From acb3b3e9589aa3e5483dc95cb4e30720bebf1fd1 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Tue, 10 Nov 2020 16:59:06 +0800 Subject: [PATCH 21/57] Readme update for table connection string (#609) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e88d2cf68..e860f2f7f 100644 --- a/README.md +++ b/README.md @@ -541,7 +541,7 @@ You can pass the following connection strings to the [Azure SDKs](https://aka.ms The full connection string is: ```bash -DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1; +DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1; ``` Take blob service only, the full connection string is: From 798f291b4b1cf4724ed21918c0cea937d43e89ed Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Tue, 10 Nov 2020 17:29:24 +0800 Subject: [PATCH 22/57] Remove console log (#610) --- src/table/persistence/LokiTableMetadataStore.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index 505d2f23d..e584433a9 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -751,9 +751,9 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { transformedQuery += ")"; // tslint:disable-next-line: no-console - console.log(query); + // console.log(query); // tslint:disable-next-line: no-console - console.log(transformedQuery); + // console.log(transformedQuery); return new Function("item", transformedQuery) as any; } From d5480d95cd9deba5ecdc05f16c50143b09aaaa32 Mon Sep 17 00:00:00 2001 From: Xiaoning Liu Date: Wed, 11 Nov 2020 10:50:58 +0800 Subject: [PATCH 23/57] Minor change --- src/table/handlers/TableHandler.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 1a0e8bf27..09ac60c69 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -471,12 +471,13 @@ export default class TableHandler extends BaseHandler implements ITableHandler { } const entities: string[] = []; + const odataPrefix = this.getOdataAnnotationUrlPrefix(tableContext, account); result.forEach((element) => { const entity = {} as any; const annotation = getEntityOdataAnnotationsForResponse( account, table, - this.getOdataAnnotationUrlPrefix(tableContext, account), + odataPrefix, element.PartitionKey, element.RowKey, accept @@ -501,13 +502,14 @@ export default class TableHandler extends BaseHandler implements ITableHandler { ); }); + // TODO: What about NO_METADATA_ACCEPT? const odatametadata = getEntityOdataAnnotationsForResponse( account, table, - this.getOdataAnnotationUrlPrefix(tableContext, account), + odataPrefix, + "", "", - "element.RowKey", accept ).odatametadata || ""; From d34eb65405af072f8cd38fa15ccb795859f64f50 Mon Sep 17 00:00:00 2001 From: Xiaoning Liu Date: Wed, 11 Nov 2020 12:30:24 +0800 Subject: [PATCH 24/57] Serialize special chars in query entity response --- src/table/entity/EdmBinary.ts | 2 +- src/table/entity/EdmBoolean.ts | 2 +- src/table/entity/EdmDateTime.ts | 4 ++-- src/table/entity/EdmDouble.ts | 2 +- src/table/entity/EdmGuid.ts | 4 ++-- src/table/entity/EdmInt32.ts | 4 ++-- src/table/entity/EdmInt64.ts | 4 ++-- src/table/entity/EdmString.ts | 4 ++-- src/table/entity/EntityProperty.ts | 7 ++++--- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/table/entity/EdmBinary.ts b/src/table/entity/EdmBinary.ts index b0a1f923f..352748942 100644 --- a/src/table/entity/EdmBinary.ts +++ b/src/table/entity/EdmBinary.ts @@ -24,7 +24,7 @@ export class EdmBinary implements IEdmType { } public toJsonPropertyValueString(name: string): string { - return `"${name}":"${this.value}"`; + return `"${name}":${JSON.stringify(this.typedValue)}`; } public toJsonPropertyTypePair( diff --git a/src/table/entity/EdmBoolean.ts b/src/table/entity/EdmBoolean.ts index a5c6cd9c9..86a46f8a7 100644 --- a/src/table/entity/EdmBoolean.ts +++ b/src/table/entity/EdmBoolean.ts @@ -21,7 +21,7 @@ export class EdmBoolean implements IEdmType { } public toJsonPropertyValueString(name: string): string { - return `"${name}":${this.value}`; + return `"${name}":${this.typedValue}`; } public toJsonPropertyTypePair( diff --git a/src/table/entity/EdmDateTime.ts b/src/table/entity/EdmDateTime.ts index 51efc1732..6cc2650f0 100644 --- a/src/table/entity/EdmDateTime.ts +++ b/src/table/entity/EdmDateTime.ts @@ -20,11 +20,11 @@ export class EdmDateTime implements IEdmType { } public toJsonPropertyValuePair(name: string): [string, string] { - return [name, this.value]; + return [name, this.typedValue]; } public toJsonPropertyValueString(name: string): string { - return `"${name}":"${this.value}"`; + return `"${name}":${JSON.stringify(this.typedValue)}`; } public toJsonPropertyTypePair( diff --git a/src/table/entity/EdmDouble.ts b/src/table/entity/EdmDouble.ts index 2f9c1f571..3232fbb5e 100644 --- a/src/table/entity/EdmDouble.ts +++ b/src/table/entity/EdmDouble.ts @@ -39,7 +39,7 @@ export class EdmDouble implements IEdmType { Number.isInteger(this.value) ? this.typedValue.toFixed(1) : this.value }`; } else { - return `"${name}":"${this.value}"`; + return `"${name}":${JSON.stringify(this.typedValue)}`; } } diff --git a/src/table/entity/EdmGuid.ts b/src/table/entity/EdmGuid.ts index 64cb419d1..ebe7b9409 100644 --- a/src/table/entity/EdmGuid.ts +++ b/src/table/entity/EdmGuid.ts @@ -20,11 +20,11 @@ export class EdmGuid implements IEdmType { } public toJsonPropertyValuePair(name: string): [string, string] { - return [name, this.value]; + return [name, this.typedValue]; } public toJsonPropertyValueString(name: string): string { - return `"${name}":"${this.value}"`; + return `"${name}":${JSON.stringify(this.typedValue)}`; } public toJsonPropertyTypePair( diff --git a/src/table/entity/EdmInt32.ts b/src/table/entity/EdmInt32.ts index 3ede1b283..1ef021b90 100644 --- a/src/table/entity/EdmInt32.ts +++ b/src/table/entity/EdmInt32.ts @@ -19,11 +19,11 @@ export class EdmInt32 implements IEdmType { } public toJsonPropertyValuePair(name: string): [string, number] { - return [name, this.value]; + return [name, this.typedValue]; } public toJsonPropertyValueString(name: string): string { - return `"${name}":${this.value}`; + return `"${name}":${this.typedValue}`; } public toJsonPropertyTypePair( diff --git a/src/table/entity/EdmInt64.ts b/src/table/entity/EdmInt64.ts index ad925ac1d..c36e88881 100644 --- a/src/table/entity/EdmInt64.ts +++ b/src/table/entity/EdmInt64.ts @@ -20,11 +20,11 @@ export class EdmInt64 implements IEdmType { } public toJsonPropertyValuePair(name: string): [string, string] { - return [name, this.value]; + return [name, this.typedValue]; } public toJsonPropertyValueString(name: string): string { - return `"${name}":"${this.value}"`; + return `"${name}":${JSON.stringify(this.typedValue)}`; } public toJsonPropertyTypePair( diff --git a/src/table/entity/EdmString.ts b/src/table/entity/EdmString.ts index 913da74a0..02ba55542 100644 --- a/src/table/entity/EdmString.ts +++ b/src/table/entity/EdmString.ts @@ -21,11 +21,11 @@ export class EdmString implements IEdmType { public toJsonPropertyValuePair( name: string ): [string, string | number | boolean] { - return [name, this.value]; + return [name, this.typedValue]; } public toJsonPropertyValueString(name: string): string { - return `"${name}":"${this.value}"`; + return `"${name}":${JSON.stringify(this.typedValue)}`; } public toJsonPropertyTypePair( diff --git a/src/table/entity/EntityProperty.ts b/src/table/entity/EntityProperty.ts index 74c14e1a8..8358dfa52 100644 --- a/src/table/entity/EntityProperty.ts +++ b/src/table/entity/EntityProperty.ts @@ -53,13 +53,14 @@ export class EntityProperty { } public toJsonPropertyTypePair( - annotationLevel: AnnotationLevel + annotationLevel: AnnotationLevel, + force: boolean = false ): [string, string] | undefined { return this.edmType.toJsonPropertyTypePair( this.name, annotationLevel, this.isSystemProperty, - true + force ); } @@ -101,7 +102,7 @@ export class EntityProperty { const [key, value] = pair; entity.properties[key] = value; - const res = this.toJsonPropertyTypePair(AnnotationLevel.FULL); + const res = this.toJsonPropertyTypePair(AnnotationLevel.FULL, true); if (res) { const [typeKey, typeValue] = res; entity.properties[typeKey] = typeValue; From f46807d8616df73082834811347f628c1f2ed181 Mon Sep 17 00:00:00 2001 From: Xiaoning Liu Date: Wed, 11 Nov 2020 12:31:35 +0800 Subject: [PATCH 25/57] Update alpha table version --- ChangeLog.md | 6 ++++++ package.json | 2 +- src/table/utils/constants.ts | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 6e009505e..90ecda7c3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,6 +4,12 @@ ## Upcoming Release +## 2020.11 Version 3.9.0-table-alpha.1 + +Table: + +- Alpha version of Azurite V3 Table. + ## 2020.10 Version 3.9.0 - Bump up Azure Storage service API version to 2020-02-10. diff --git a/package.json b/package.json index 86481bec8..3089719df 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Azurite", "description": "An open source Azure Storage API compatible server", "icon": "icon.png", - "version": "3.9.0", + "version": "3.9.0-table-alpha.1", "publisher": "Azurite", "categories": [ "Other" diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index 7d99be545..eb4ae9aa0 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -17,7 +17,7 @@ export const TABLE_API_VERSION = "2019-12-12"; export const HeaderConstants = { SERVER: "Server", - VERSION: "3.8.0", + VERSION: "3.8.0-tablealpha.1", APPLICATION_JSON: "application/json", AUTHORIZATION: "authorization", CONTENT_MD5: "content-md5", From 802215cd7aa64867b37fbd3782e574ed7dabc13c Mon Sep 17 00:00:00 2001 From: Xiaoning Liu Date: Wed, 11 Nov 2020 17:13:03 +0800 Subject: [PATCH 26/57] Remove test in docker build; Remove scr/typing files in npm package; Update changelog for table alpha.1 --- .dockerignore | 2 ++ .npmignore | 5 +++++ ChangeLog.md | 2 +- Dockerfile | 1 - src/table/authentication/IAccountSASSignatureValues.ts | 2 +- src/table/utils/constants.ts | 2 +- 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.dockerignore b/.dockerignore index d68cab6f4..ac5d4372b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,6 @@ .vscode/** +.github/** +.github node_modules/** swagger/** __blobstorage__/** diff --git a/.npmignore b/.npmignore index 3fc8b4efb..395d0e634 100644 --- a/.npmignore +++ b/.npmignore @@ -1,5 +1,9 @@ node_modules/ +src/ +typings/ coverage +.prettierrc.json +README.mcr.md azurite-testdrive/ .nyc_output debug.log @@ -8,6 +12,7 @@ azure-pipelines.yml ISSUE_TEMPLATE.md PULL_REQUEST_TEMPLATE.md .vscode/ +.github/ tslint.json tsconfig.json *.vsix diff --git a/ChangeLog.md b/ChangeLog.md index 90ecda7c3..06cf5f2ee 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -8,7 +8,7 @@ Table: -- Alpha version of Azurite V3 Table. +- First Alpha version of Azurite V3 Table. ## 2020.10 Version 3.9.0 diff --git a/Dockerfile b/Dockerfile index 2b6a842e0..b5fb5e8dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,7 +14,6 @@ RUN npm config set unsafe-perm=true && \ COPY src ./src COPY tests ./tests RUN npm run build && \ - npm run test && \ npm install -g --loglevel verbose diff --git a/src/table/authentication/IAccountSASSignatureValues.ts b/src/table/authentication/IAccountSASSignatureValues.ts index 7b0e6e48f..770e2acfd 100644 --- a/src/table/authentication/IAccountSASSignatureValues.ts +++ b/src/table/authentication/IAccountSASSignatureValues.ts @@ -1,4 +1,4 @@ -import { IIPRange } from "@azure/storage-blob"; +import { SasIPRange as IIPRange } from "@azure/storage-blob"; import { computeHMACSHA256, diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index eb4ae9aa0..73fb5420c 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -17,7 +17,7 @@ export const TABLE_API_VERSION = "2019-12-12"; export const HeaderConstants = { SERVER: "Server", - VERSION: "3.8.0-tablealpha.1", + VERSION: "3.9.0-table-alpha.1", APPLICATION_JSON: "application/json", AUTHORIZATION: "authorization", CONTENT_MD5: "content-md5", From dece65f86a530df824ea38da6fdd16c75db9fcb5 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Thu, 12 Nov 2020 12:37:12 +0800 Subject: [PATCH 27/57] Table fix for select and accept (#615) * Ignore empty select query parameter * Compatible space in accept header value; Support Tables() create table op; Fix #613 --- src/table/handlers/TableHandler.ts | 14 +++++++++++--- .../middleware/tableStorageContext.middleware.ts | 4 +++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 09ac60c69..61e09f1c5 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -465,8 +465,11 @@ export default class TableHandler extends BaseHandler implements ITableHandler { let selectSet: Set | undefined; const selectArray = options.queryOptions?.select ?.split(",") + .filter((item) => { + return typeof item === "string" && item.length > 0; + }) .map((item) => item.trim()); - if (selectArray) { + if (selectArray && selectArray.length > 0) { selectSet = new Set(selectArray); } @@ -588,8 +591,11 @@ export default class TableHandler extends BaseHandler implements ITableHandler { let selectSet: Set | undefined; const selectArray = options.queryOptions?.select ?.split(",") + .filter((item) => { + return typeof item === "string" && item.length > 0; + }) .map((item) => item.trim()); - if (selectArray) { + if (selectArray && selectArray.length > 0) { selectSet = new Set(selectArray); } @@ -798,7 +804,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { formatParameter = context.request!.getQuery("$format"); } - if (format === XML_METADATA) { + if (format === "") { format = XML_METADATA; } @@ -810,6 +816,8 @@ export default class TableHandler extends BaseHandler implements ITableHandler { format = MINIMAL_METADATA_ACCEPT; } + format = format?.replace(/\s/g, ""); + if ( format !== NO_METADATA_ACCEPT && format !== MINIMAL_METADATA_ACCEPT && diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index 53d0ce95f..a8d7ccdea 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -79,6 +79,7 @@ export function tableStorageContextMiddleware( // Candidate tableSection // undefined - Set Table Service Properties // Tables - Create Tables, Query Tables + // Tables() - Create Tables, Query Tables // Tables('mytable') - Delete Tables, Query Entities // mytable - Get/Set Table ACL, Insert Entity, Query Entities // mytable(PartitionKey='',RowKey='') - @@ -88,8 +89,9 @@ export function tableStorageContextMiddleware( if (tableSection === undefined) { // Service level operation tableContext.tableName = undefined; - } else if (tableSection === "Tables") { + } else if (tableSection === "Tables" || tableSection === "Tables()") { // Table name in request body + tableSection = "Tables"; tableContext.tableName = undefined; } else if ( tableSection.startsWith("Tables('") && From e99fa46807a8bc8449be77d3dc1e55a64c32a07c Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Thu, 12 Nov 2020 16:01:50 +0800 Subject: [PATCH 28/57] Add 2019-10-10 as avaiable API version; Keep lease after override blob; (#617) --- package-lock.json | 2 +- src/blob/persistence/LokiBlobMetadataStore.ts | 7 +++---- src/blob/persistence/SqlBlobMetadataStore.ts | 7 +++---- src/blob/utils/constants.ts | 1 + src/queue/utils/constants.ts | 1 + src/table/utils/constants.ts | 1 + 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24f174579..ee9266bd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "azurite", - "version": "3.9.0", + "version": "3.9.0-table-alpha.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/blob/persistence/LokiBlobMetadataStore.ts b/src/blob/persistence/LokiBlobMetadataStore.ts index 5be817173..3f1f6d3bf 100644 --- a/src/blob/persistence/LokiBlobMetadataStore.ts +++ b/src/blob/persistence/LokiBlobMetadataStore.ts @@ -970,10 +970,9 @@ export default class LokiBlobMetadataStore } if (blobDoc) { - LeaseFactory.createLeaseState( - new BlobLeaseAdapter(blobDoc), - context - ).validate(new BlobWriteLeaseValidator(leaseAccessConditions)); + LeaseFactory.createLeaseState(new BlobLeaseAdapter(blobDoc), context) + .validate(new BlobWriteLeaseValidator(leaseAccessConditions)) + .sync(new BlobLeaseSyncer(blob)); // Keep original blob lease if ( blobDoc.properties !== undefined && diff --git a/src/blob/persistence/SqlBlobMetadataStore.ts b/src/blob/persistence/SqlBlobMetadataStore.ts index 806305b0f..47963020f 100644 --- a/src/blob/persistence/SqlBlobMetadataStore.ts +++ b/src/blob/persistence/SqlBlobMetadataStore.ts @@ -1154,10 +1154,9 @@ export default class SqlBlobMetadataStore implements IBlobMetadataStore { blobFindResult ); - LeaseFactory.createLeaseState( - new BlobLeaseAdapter(blobModel), - context - ).validate(new BlobWriteLeaseValidator(leaseAccessConditions)); + LeaseFactory.createLeaseState(new BlobLeaseAdapter(blobModel), context) + .validate(new BlobWriteLeaseValidator(leaseAccessConditions)) + .sync(new BlobLeaseSyncer(blob)); // Keep original blob lease; if ( blobModel.properties !== undefined && diff --git a/src/blob/utils/constants.ts b/src/blob/utils/constants.ts index 4f60df203..d3111c10e 100644 --- a/src/blob/utils/constants.ts +++ b/src/blob/utils/constants.ts @@ -98,6 +98,7 @@ export const DEFAULT_BLOB_PERSISTENCE_ARRAY: StoreDestinationArray = [ export const ValidAPIVersions = [ "2020-02-10", "2019-12-12", + "2019-10-10", "2019-07-07", "2019-02-02", "2018-11-09", diff --git a/src/queue/utils/constants.ts b/src/queue/utils/constants.ts index f91f06bb2..df4986124 100644 --- a/src/queue/utils/constants.ts +++ b/src/queue/utils/constants.ts @@ -92,6 +92,7 @@ export const DEFAULT_QUEUE_PERSISTENCE_ARRAY: StoreDestinationArray = [ export const ValidAPIVersions = [ "2020-02-10", "2019-12-12", + "2019-10-10", "2019-07-07", "2019-02-02", "2018-11-09", diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index 73fb5420c..8f6846e22 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -44,6 +44,7 @@ export const RETURN_CONTENT = "return-content"; export const QUERY_RESULT_MAX_NUM = 1000; export const ValidAPIVersions = [ "2019-12-12", + "2019-10-10", "2019-07-07", "2019-02-02", "2018-11-09", From c828ed057e03bbf6346b720fd30dfef8a2c5a55e Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Fri, 13 Nov 2020 17:52:40 +0800 Subject: [PATCH 29/57] Table alpha fix #621 #620 (#622) * Return 404 instead 409 when entity doesn't exist. Fix #621 * Compatible query entity with empty pk & rk. Fix #620 * Fix UT failures --- .../authentication/AccountSASAuthenticator.ts | 24 +-- .../authentication/TableSASAuthenticator.ts | 18 +- .../TableSharedKeyAuthenticator.ts | 2 +- .../TableSharedKeyLiteAuthenticator.ts | 2 +- src/table/errors/NotImplementedError.ts | 7 +- src/table/errors/StorageError.ts | 26 +-- src/table/errors/StorageErrorFactory.ts | 63 +++--- src/table/handlers/ServiceHandler.ts | 9 +- src/table/handlers/TableHandler.ts | 179 +++--------------- .../AuthenticationMiddlewareFactory.ts | 6 +- .../tableStorageContext.middleware.ts | 21 +- .../persistence/LokiTableMetadataStore.ts | 8 +- src/table/utils/utils.ts | 29 ++- tests/table/apis/table.entity.test.ts | 26 +-- tests/table/sas.test.ts | 20 +- 15 files changed, 161 insertions(+), 279 deletions(-) diff --git a/src/table/authentication/AccountSASAuthenticator.ts b/src/table/authentication/AccountSASAuthenticator.ts index 6c212969f..587e89df9 100644 --- a/src/table/authentication/AccountSASAuthenticator.ts +++ b/src/table/authentication/AccountSASAuthenticator.ts @@ -43,7 +43,7 @@ export default class AccountSASAuthenticator implements IAuthenticator { const accountProperties = this.accountDataStore.getAccount(account); if (accountProperties === undefined) { throw StorageErrorFactory.getInvalidOperation( - context.contextID!, + context, "Invalid storage account." ); } @@ -155,7 +155,7 @@ export default class AccountSASAuthenticator implements IAuthenticator { `AccountSASAuthenticator:validate() Validate start and expiry failed.`, context.contextID ); - throw StorageErrorFactory.getAuthorizationFailure(context.contextID!); + throw StorageErrorFactory.getAuthorizationFailure(context); } this.logger.info( @@ -167,9 +167,7 @@ export default class AccountSASAuthenticator implements IAuthenticator { `AccountSASAuthenticator:validate() Validate IP range failed.`, context.contextID ); - throw StorageErrorFactory.getAuthorizationSourceIPMismatch( - context.contextID! - ); + throw StorageErrorFactory.getAuthorizationSourceIPMismatch(context); } this.logger.info( @@ -181,9 +179,7 @@ export default class AccountSASAuthenticator implements IAuthenticator { `AccountSASAuthenticator:validate() Validate protocol failed.`, context.contextID ); - throw StorageErrorFactory.getAuthorizationProtocolMismatch( - context.contextID! - ); + throw StorageErrorFactory.getAuthorizationProtocolMismatch(context); } const operation = context.operation; @@ -211,21 +207,15 @@ export default class AccountSASAuthenticator implements IAuthenticator { } if (!accountSASPermission.validateServices(values.services)) { - throw StorageErrorFactory.getAuthorizationServiceMismatch( - context.contextID! - ); + throw StorageErrorFactory.getAuthorizationServiceMismatch(context); } if (!accountSASPermission.validateResourceTypes(values.resourceTypes)) { - throw StorageErrorFactory.getAuthorizationResourceTypeMismatch( - context.contextID! - ); + throw StorageErrorFactory.getAuthorizationResourceTypeMismatch(context); } if (!accountSASPermission.validatePermissions(values.permissions)) { - throw StorageErrorFactory.getAuthorizationPermissionMismatch( - context.contextID! - ); + throw StorageErrorFactory.getAuthorizationPermissionMismatch(context); } this.logger.info( diff --git a/src/table/authentication/TableSASAuthenticator.ts b/src/table/authentication/TableSASAuthenticator.ts index 574c56ad8..351fbfe2d 100644 --- a/src/table/authentication/TableSASAuthenticator.ts +++ b/src/table/authentication/TableSASAuthenticator.ts @@ -63,7 +63,7 @@ export default class TableSASAuthenticator implements IAuthenticator { const accountProperties = this.accountDataStore.getAccount(account); if (accountProperties === undefined) { throw StorageErrorFactory.getInvalidOperation( - context.contextID!, + context, "Invalid storage account." ); } @@ -194,7 +194,7 @@ export default class TableSASAuthenticator implements IAuthenticator { `TableSASAuthenticator:validate() Cannot get access policy defined for table ${tableName} with id ${values.identifier}.`, context.contextID ); - throw StorageErrorFactory.getAuthorizationFailure(context.contextID!); + throw StorageErrorFactory.getAuthorizationFailure(context); } values.startTime = accessPolicy.start; @@ -211,7 +211,7 @@ export default class TableSASAuthenticator implements IAuthenticator { `TableSASAuthenticator:validate() Validate start and expiry failed.`, context.contextID ); - throw StorageErrorFactory.getAuthorizationFailure(context.contextID!); + throw StorageErrorFactory.getAuthorizationFailure(context); } this.logger.info( @@ -223,9 +223,7 @@ export default class TableSASAuthenticator implements IAuthenticator { `TableSASAuthenticator:validate() Validate IP range failed.`, context.contextID ); - throw StorageErrorFactory.getAuthorizationSourceIPMismatch( - context.contextID! - ); + throw StorageErrorFactory.getAuthorizationSourceIPMismatch(context); } this.logger.info( @@ -237,9 +235,7 @@ export default class TableSASAuthenticator implements IAuthenticator { `TableSASAuthenticator:validate() Validate protocol failed.`, context.contextID ); - throw StorageErrorFactory.getAuthorizationProtocolMismatch( - context.contextID! - ); + throw StorageErrorFactory.getAuthorizationProtocolMismatch(context); } const operation = context.operation; @@ -270,9 +266,7 @@ export default class TableSASAuthenticator implements IAuthenticator { } if (!tableSASPermission.validatePermissions(values.permissions!)) { - throw StorageErrorFactory.getAuthorizationPermissionMismatch( - context.contextID! - ); + throw StorageErrorFactory.getAuthorizationPermissionMismatch(context); } this.logger.info( diff --git a/src/table/authentication/TableSharedKeyAuthenticator.ts b/src/table/authentication/TableSharedKeyAuthenticator.ts index b7ddc7c88..7c31198b6 100644 --- a/src/table/authentication/TableSharedKeyAuthenticator.ts +++ b/src/table/authentication/TableSharedKeyAuthenticator.ts @@ -44,7 +44,7 @@ export default class TableSharedKeyAuthenticator implements IAuthenticator { tableContext.contextID ); throw StorageErrorFactory.getInvalidOperation( - tableContext.contextID!, + tableContext, "Invalid storage account." ); } diff --git a/src/table/authentication/TableSharedKeyLiteAuthenticator.ts b/src/table/authentication/TableSharedKeyLiteAuthenticator.ts index 5cf411471..303c7051b 100644 --- a/src/table/authentication/TableSharedKeyLiteAuthenticator.ts +++ b/src/table/authentication/TableSharedKeyLiteAuthenticator.ts @@ -47,7 +47,7 @@ export default class TableSharedKeyLiteAuthenticator implements IAuthenticator { tableContext.contextID ); throw StorageErrorFactory.getInvalidOperation( - tableContext.contextID!, + tableContext, "Invalid storage account." ); } diff --git a/src/table/errors/NotImplementedError.ts b/src/table/errors/NotImplementedError.ts index 84940ac79..469b0f197 100644 --- a/src/table/errors/NotImplementedError.ts +++ b/src/table/errors/NotImplementedError.ts @@ -1,3 +1,4 @@ +import Context from "../generated/Context"; import StorageError from "./StorageError"; /** @@ -8,12 +9,14 @@ import StorageError from "./StorageError"; * @extends {StorageError} */ export default class NotImplementedError extends StorageError { - public constructor(requestID: string = "") { + public constructor(context: Context) { super( 501, "APINotImplemented", "Current API is not implemented yet. Please vote your wanted features to https://github.com/azure/azurite/issues", - requestID + context.contextID || "", + undefined, + context ); } } diff --git a/src/table/errors/StorageError.ts b/src/table/errors/StorageError.ts index 339f6cbe6..eac709909 100644 --- a/src/table/errors/StorageError.ts +++ b/src/table/errors/StorageError.ts @@ -7,6 +7,7 @@ import { import Context from "../generated/Context"; import MiddlewareError from "../generated/errors/MiddlewareError"; import { jsonToXML } from "../generated/utils/xml"; +import { getPayloadFormat } from "../utils/utils"; /** * Represents an Azure Storage Server Error. @@ -38,24 +39,13 @@ export default class StorageError extends MiddlewareError { storageErrorMessage: string, storageRequestID: string, storageAdditionalErrorMessages: { [key: string]: string } = {}, - context?: Context + context: Context ) { - let isJSON = false; - let accept = - context && context.request - ? context.request.getHeader("accept") - : undefined; - accept = - context && context.request - ? context.request.getQuery("$format") || accept - : accept; - if ( - accept === NO_METADATA_ACCEPT || - accept === MINIMAL_METADATA_ACCEPT || - accept === FULL_METADATA_ACCEPT - ) { - isJSON = true; - } + const pyaload = getPayloadFormat(context); + const isJSON = + pyaload === NO_METADATA_ACCEPT || + pyaload === MINIMAL_METADATA_ACCEPT || + pyaload === FULL_METADATA_ACCEPT; const bodyInJSON: any = isJSON ? { @@ -91,7 +81,7 @@ export default class StorageError extends MiddlewareError { "x-ms-version": TABLE_API_VERSION }, body, - isJSON ? `${accept};streaming=true;charset=utf-8` : "application/xml" + isJSON ? `${pyaload};streaming=true;charset=utf-8` : "application/xml" ); this.name = "StorageError"; diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 0574aa2a5..060b6f50c 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -11,7 +11,7 @@ const defaultID: string = "DefaultID"; export default class StorageErrorFactory { public static getInvalidHeaderValue( - contextID: string = "", + context: Context, additionalMessages?: { [key: string]: string } ): StorageError { if (additionalMessages === undefined) { @@ -21,8 +21,9 @@ export default class StorageErrorFactory { 400, "InvalidHeaderValue", "The value for one of the HTTP headers is not in the correct format.", - contextID, - additionalMessages + context.contextID || defaultID, + additionalMessages, + context ); } @@ -66,64 +67,81 @@ export default class StorageErrorFactory { } public static getInvalidOperation( - contextID: string, + context: Context, message: string = "" ): StorageError { - return new StorageError(400, "InvalidOperation", message, contextID); + return new StorageError( + 400, + "InvalidOperation", + message, + context.contextID || "", + undefined, + context + ); } public static getAuthorizationSourceIPMismatch( - contextID: string + context: Context ): StorageError { return new StorageError( 403, "AuthorizationSourceIPMismatch", "This request is not authorized to perform this operation using this source IP {SourceIP}.", - contextID + context.contextID || defaultID, + undefined, + context ); } public static getAuthorizationProtocolMismatch( - contextID: string + context: Context ): StorageError { return new StorageError( 403, "AuthorizationProtocolMismatch", "This request is not authorized to perform this operation using this protocol.", - contextID + context.contextID || defaultID, + undefined, + context ); } public static getAuthorizationPermissionMismatch( - contextID: string + context: Context ): StorageError { return new StorageError( 403, "AuthorizationPermissionMismatch", "This request is not authorized to perform this operation using this permission.", - contextID + context.contextID || defaultID, + undefined, + context ); } public static getAuthorizationServiceMismatch( - contextID: string + context: Context ): StorageError { return new StorageError( 403, "AuthorizationServiceMismatch", "This request is not authorized to perform this operation using this service.", - contextID + context.contextID || defaultID, + undefined, + context ); } public static getAuthorizationResourceTypeMismatch( - contextID: string + context: Context ): StorageError { return new StorageError( 403, "AuthorizationResourceTypeMismatch", "This request is not authorized to perform this operation using this resource type.", - contextID + context.contextID || defaultID, + undefined, + context ); } @@ -149,21 +167,12 @@ export default class StorageErrorFactory { ); } - public static getAuthorizationFailure(contextID: string): StorageError { + public static getAuthorizationFailure(context: Context): StorageError { return new StorageError( 403, "AuthorizationFailure", // tslint:disable-next-line:max-line-length "Server failed to authenticate the request. Make sure the value of the Authorization header is formed correctly including the signature.", - contextID - ); - } - - public static getEntityNotExist(context: Context): StorageError { - return new StorageError( - 409, - "EntityDoesNotExist", - "The entity to update doesn't exist in the table.", context.contextID || defaultID, undefined, context @@ -228,8 +237,8 @@ export default class StorageErrorFactory { public static getEntityNotFound(context: Context): StorageError { return new StorageError( 404, - "EntityNotFound", - "The specified entity does not exist.", + "ResourceNotFound", + "The specified resource does not exist.", context.contextID || defaultID, undefined, context diff --git a/src/table/handlers/ServiceHandler.ts b/src/table/handlers/ServiceHandler.ts index 45db071d5..b46aefe26 100644 --- a/src/table/handlers/ServiceHandler.ts +++ b/src/table/handlers/ServiceHandler.ts @@ -4,7 +4,8 @@ import Context from "../generated/Context"; import IServiceHandler from "../generated/handlers/IServiceHandler"; import BaseHandler from "./BaseHandler"; -export default class ServiceHandler extends BaseHandler +export default class ServiceHandler + extends BaseHandler implements IServiceHandler { public async setProperties( tableServiceProperties: Models.TableServiceProperties, @@ -12,7 +13,7 @@ export default class ServiceHandler extends BaseHandler context: Context ): Promise { // TODO Refer to Blob/Queue ServiceHandler implementation - throw new NotImplementedError(); + throw new NotImplementedError(context); } public async getProperties( @@ -20,7 +21,7 @@ export default class ServiceHandler extends BaseHandler context: Context ): Promise { // TODO Refer to Blob/Queue ServiceHandler implementation - throw new NotImplementedError(); + throw new NotImplementedError(context); } public async getStatistics( @@ -28,6 +29,6 @@ export default class ServiceHandler extends BaseHandler context: Context ): Promise { // TODO Refer to Blob/Queue ServiceHandler implementation - throw new NotImplementedError(); + throw new NotImplementedError(context); } } diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 61e09f1c5..d65543619 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -17,11 +17,11 @@ import { NO_METADATA_ACCEPT, RETURN_CONTENT, RETURN_NO_CONTENT, - TABLE_API_VERSION, - XML_METADATA + TABLE_API_VERSION } from "../utils/constants"; import { getEntityOdataAnnotationsForResponse, + getPayloadFormat, getTableOdataAnnotationsForResponse, getTablePropertiesOdataAnnotationsForResponse, updateTableOptionalOdataAnnotationsForResponse @@ -238,7 +238,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { ); } - response.contentType = "application/json"; + this.updateResponseAccept(tableContext, accept); this.updateResponsePrefer(response, tableContext); return response; @@ -505,20 +505,20 @@ export default class TableHandler extends BaseHandler implements ITableHandler { ); }); - // TODO: What about NO_METADATA_ACCEPT? - const odatametadata = - getEntityOdataAnnotationsForResponse( - account, - table, - odataPrefix, - "", - "", - accept - ).odatametadata || ""; + const odatametadata = getEntityOdataAnnotationsForResponse( + account, + table, + odataPrefix, + "", + "", + accept + ).odatametadata; + + const odatametadataPariString = odatametadata + ? `"odata.metadata":${JSON.stringify(odatametadata)},` + : ""; - const body = `{"odata.metadata":${JSON.stringify( - odatametadata - )},"value":[${entities.join(",")}]}`; + const body = `{${odatametadataPariString}"value":[${entities.join(",")}]}`; response.body = new BufferStream(Buffer.from(body)); this.logger.debug( @@ -526,7 +526,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { context.contextID ); - context.response!.setContentType("application/json"); + this.updateResponseAccept(tableContext, accept); return response; } @@ -554,7 +554,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { ); if (entity === undefined || entity === null) { - throw StorageErrorFactory.getEntityNotExist(context); + throw StorageErrorFactory.getEntityNotFound(context); } const response: Models.TableQueryEntitiesWithPartitionAndRowKeyResponse = { @@ -604,7 +604,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { Buffer.from(nomarlizedEntity.toResponseString(accept, body, selectSet)) ); - context.response!.setContentType("application/json"); + this.updateResponseAccept(tableContext, accept); return response; } @@ -634,7 +634,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { // const accountName = tableContext.account; // const tableName = tableContext.tableName; // Get tableName from context // TODO - throw new NotImplementedError(); + throw new NotImplementedError(context); } public async setAccessPolicy( @@ -647,7 +647,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { // const accountName = tableContext.account; // const tableName = tableContext.tableName; // Get tableName from context // TODO - throw new NotImplementedError(); + throw new NotImplementedError(context); } public async batch( @@ -668,118 +668,6 @@ export default class TableHandler extends BaseHandler implements ITableHandler { }; } - // private getResponseBodyFromQueryResultBasedOnAccept( - // accept: string, - // accountName: string, - // tableContext: Context, - // queryResult: { [propertyName: string]: any }[] - // ) { - // let protocol = "http"; - // let host = - // DEFAULT_TABLE_SERVER_HOST_NAME + ":" + DEFAULT_TABLE_LISTENING_PORT; - - // if (tableContext.request !== undefined) { - // host = tableContext.request.getHeader("host") as string; - // protocol = tableContext.request.getProtocol() as string; - // } - - // const resultWithMetaData: { [propertyName: string]: any }[] = []; - // const responseBody: { [propertyName: string]: any } = {}; - - // switch (accept) { - // case MINIMAL_METADATA_ACCEPT: { - // // Add odata.metadata - // (responseBody as any)["odata.metadata"] = - // `${protocol}://${host}/` + queryResult[0].odataMetadata; - // for (const entity of queryResult) { - // const filteredEntity = {}; - // for (const key of Object.keys(entity)) { - // // Only need metadata and properties' odata type - // if ( - // key === "odataMetadata" || - // key === "odataType" || - // key === "odataId" || - // key === "eTag" || - // key === "odataEditLink" - // ) { - // continue; - // } - // // Also add odataType to each field - // (filteredEntity as any)[key] = entity[key]; - // } - - // resultWithMetaData.push(filteredEntity); - // } - // (responseBody as any).value = resultWithMetaData; - // break; - // } - // case FULL_METADATA_ACCEPT: { - // // Add odata.metadata - // (responseBody as any)["odata.metadata"] = queryResult[0].odataMetadata; - // for (const entity of queryResult) { - // const filteredEntity = {}; - // for (const key of Object.keys(entity)) { - // // Remove odataMetadata of each entity - // if (key === "odataMetadata") { - // continue; - // } - // (filteredEntity as any)[key] = entity[key]; - // } - - // // Add Timestamp@odata.type - // (filteredEntity as any)["Timestamp@odata.type"] = "Edm.DateTime"; - - // // Solve the name inconsistency of the response and entity - // (filteredEntity as any)[ - // "odata.type" - // ] = (filteredEntity as any).odataType; - // delete (filteredEntity as any).odataType; - - // (filteredEntity as any)["odata.id"] = - // `${protocol}://${host}/` + (filteredEntity as any).odataId; - // delete (filteredEntity as any).odataId; - - // (filteredEntity as any)["odata.etag"] = (filteredEntity as any).eTag; - // delete (filteredEntity as any).eTag; - - // (filteredEntity as any)[ - // "odata.editLink" - // ] = (filteredEntity as any).odataEditLink; - // delete (filteredEntity as any).odataEditLink; - - // // Add processed entity back - // resultWithMetaData.push(filteredEntity); - // } - // (responseBody as any).value = resultWithMetaData; - // break; - // } - // default: { - // for (const entity of queryResult) { - // const filteredEntity = {}; - // for (const key of Object.keys(entity)) { - // // Don't need metadata and properties' odata type - // if ( - // key === "odataMetadata" || - // key === "odataType" || - // key === "odataId" || - // key === "eTag" || - // key === "odataEditLink" || - // key.indexOf("@odata.type") > 0 - // ) { - // continue; - // } - // (filteredEntity as any)[key] = entity[key]; - // } - - // resultWithMetaData.push(filteredEntity); - // } - // (responseBody as any).value = resultWithMetaData; - // break; - // } - // } - // return responseBody; - // } - private getOdataAnnotationUrlPrefix( tableContext: TableStorageContext, account: string @@ -794,29 +682,8 @@ export default class TableHandler extends BaseHandler implements ITableHandler { return `${protocol}://${host}`; } - private getAndCheckPayloadFormat( - context: TableStorageContext, - formatParameter?: string - ): string { - let format = context.request!.getHeader(HeaderConstants.ACCEPT); - - if (formatParameter === undefined) { - formatParameter = context.request!.getQuery("$format"); - } - - if (format === "") { - format = XML_METADATA; - } - - if (typeof formatParameter === "string") { - format = formatParameter; - } - - if (format === "application/json") { - format = MINIMAL_METADATA_ACCEPT; - } - - format = format?.replace(/\s/g, ""); + private getAndCheckPayloadFormat(context: TableStorageContext): string { + const format = getPayloadFormat(context); if ( format !== NO_METADATA_ACCEPT && diff --git a/src/table/middleware/AuthenticationMiddlewareFactory.ts b/src/table/middleware/AuthenticationMiddlewareFactory.ts index f90766cfb..1b0c148be 100644 --- a/src/table/middleware/AuthenticationMiddlewareFactory.ts +++ b/src/table/middleware/AuthenticationMiddlewareFactory.ts @@ -19,13 +19,11 @@ export default class AuthenticationMiddlewareFactory { DEFAULT_TABLE_CONTEXT_PATH ); this.authenticate(req, res, authenticators) - .then(pass => { + .then((pass) => { if (pass) { next(); } else { - next( - StorageErrorFactory.getAuthorizationFailure(context.contextID!) - ); + next(StorageErrorFactory.getAuthorizationFailure(context)); } }) .catch(next); diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index a8d7ccdea..321367224 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -41,13 +41,6 @@ export function tableStorageContextMiddleware( const requestID = uuid(); - if (!skipApiVersionCheck) { - const apiVersion = req.header(HeaderConstants.X_MS_VERSION); - if (apiVersion !== undefined) { - checkApiVersion(apiVersion, ValidAPIVersions, requestID); - } - } - const tableContext = new TableStorageContext( res.locals, DEFAULT_TABLE_CONTEXT_PATH @@ -57,6 +50,13 @@ export function tableStorageContextMiddleware( tableContext.startTime = new Date(); tableContext.xMsRequestID = requestID; + if (!skipApiVersionCheck) { + const apiVersion = req.header(HeaderConstants.X_MS_VERSION); + if (apiVersion !== undefined) { + checkApiVersion(apiVersion, ValidAPIVersions, tableContext); + } + } + logger.info( `TableStorageContextMiddleware: RequestMethod=${req.method} RequestURL=${ req.protocol @@ -135,6 +135,8 @@ export function tableStorageContextMiddleware( thridQuoteIndex + 1, fourthQuoteIndex ); + + tableSection = `${tableContext.tableName}(PartitionKey='PLACEHOLDER',RowKey='PLACEHOLDER')`; } else if ( tableSection.includes("(") && tableSection.includes(")") && @@ -165,6 +167,11 @@ export function tableStorageContextMiddleware( tableContext.dispatchPattern = tableSection !== undefined ? `/${tableSection}` : "/"; + logger.debug( + `tableStorageContextMiddleware: Dispatch pattern string: ${tableContext.dispatchPattern}`, + requestID + ); + logger.info( `tableStorageContextMiddleware: Account=${account} tableName=${tableContext.tableName}`, requestID diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index e584433a9..28ed5dc3d 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -507,7 +507,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { table: string ): Promise { // TODO - throw new NotImplementedError(); + throw new NotImplementedError(context); } public async setTableAccessPolicy( @@ -515,7 +515,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { table: string ): Promise { // TODO - throw new NotImplementedError(); + throw new NotImplementedError(context); } private async updateTableEntity( @@ -547,7 +547,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { }) as Entity; if (!doc) { - throw StorageErrorFactory.getEntityNotExist(context); + throw StorageErrorFactory.getEntityNotFound(context); } // Test if etag value is valid @@ -593,7 +593,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { }) as Entity; if (!doc) { - throw StorageErrorFactory.getEntityNotExist(context); + throw StorageErrorFactory.getEntityNotFound(context); } if (ifMatch === undefined || ifMatch === "*" || doc.eTag === ifMatch) { diff --git a/src/table/utils/utils.ts b/src/table/utils/utils.ts index 498171459..80cd0df51 100644 --- a/src/table/utils/utils.ts +++ b/src/table/utils/utils.ts @@ -1,5 +1,6 @@ import StorageErrorFactory from "../errors/StorageErrorFactory"; import { TableResponseProperties } from "../generated/artifacts/models"; +import Context from "../generated/Context"; import { Entity, IOdataAnnotations, @@ -9,7 +10,8 @@ import { import { FULL_METADATA_ACCEPT, HeaderConstants, - MINIMAL_METADATA_ACCEPT + MINIMAL_METADATA_ACCEPT, + XML_METADATA } from "./constants"; export function getTableOdataAnnotationsForRequest( @@ -219,10 +221,10 @@ export function getOdataAnnotations( export function checkApiVersion( inputApiVersion: string, validApiVersions: Array, - requestId: string + context: Context ): void { if (!validApiVersions.includes(inputApiVersion)) { - throw StorageErrorFactory.getInvalidHeaderValue(requestId, { + throw StorageErrorFactory.getInvalidHeaderValue(context, { HeaderName: HeaderConstants.X_MS_VERSION, HeaderValue: inputApiVersion }); @@ -232,3 +234,24 @@ export function checkApiVersion( export function getTimestampString(date: Date): string { return date.toISOString().replace("Z", "0000Z"); } + +export function getPayloadFormat(context: Context): string { + let format = context.request?.getHeader(HeaderConstants.ACCEPT); + + const formatParameter = context.request?.getQuery("$format"); + if (typeof formatParameter === "string") { + format = formatParameter; + } + + if (format === undefined || format === "") { + format = XML_METADATA; + } + + if (format === "application/json") { + format = MINIMAL_METADATA_ACCEPT; + } + + format = format.replace(/\s/g, ""); + + return format; +} diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index acfe71025..4468eaf9a 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -66,7 +66,7 @@ describe("table Entity APIs test", () => { // Simple test in here until we have the full set checked in, as we need // a starting point for delete and query entity APIs - it("Should insert new Entity, @loki", done => { + it("Should insert new Entity, @loki", (done) => { // https://docs.microsoft.com/en-us/rest/api/storageservices/insert-entity const entity = { PartitionKey: "part1", @@ -79,7 +79,7 @@ describe("table Entity APIs test", () => { }); }); - it("Should delete an Entity using etag wildcard, @loki", done => { + it("Should delete an Entity using etag wildcard, @loki", (done) => { // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1 const entity = { PartitionKey: "part1", @@ -103,7 +103,7 @@ describe("table Entity APIs test", () => { }); }); - it("Should not delete an Entity not matching Etag, @loki", done => { + it("Should not delete an Entity not matching Etag, @loki", (done) => { // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1 const entityInsert = { PartitionKey: "part1", @@ -144,7 +144,7 @@ describe("table Entity APIs test", () => { ); }); - it("Should delete a matching Etag, @loki", done => { + it("Should delete a matching Etag, @loki", (done) => { // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1 const entityInsert = { PartitionKey: "part1", @@ -182,7 +182,7 @@ describe("table Entity APIs test", () => { ); }); - it("Update an Entity that exists, @loki", done => { + it("Update an Entity that exists, @loki", (done) => { const entityInsert = { PartitionKey: "part1", RowKey: "row3", @@ -215,14 +215,14 @@ describe("table Entity APIs test", () => { ); }); - it("Update an Entity that does not exist, @loki", done => { + it("Update an Entity that does not exist, @loki", (done) => { tableService.replaceEntity( tableName, { PartitionKey: "part1", RowKey: "row4", myValue: "newValue" }, (updateError, updateResult, updateResponse) => { const castUpdateStatusCode = (updateError as StorageError).statusCode; if (updateError) { - assert.equal(castUpdateStatusCode, 409); + assert.equal(castUpdateStatusCode, 404); done(); } else { assert.fail("Test failed to throw the right Error" + updateError); @@ -231,7 +231,7 @@ describe("table Entity APIs test", () => { ); }); - it("Should not update an Entity not matching Etag, @loki", done => { + it("Should not update an Entity not matching Etag, @loki", (done) => { const entityInsert = { PartitionKey: "part1", RowKey: "row4", @@ -273,7 +273,7 @@ describe("table Entity APIs test", () => { ); }); - it("Should update, if Etag matches, @loki", done => { + it("Should update, if Etag matches, @loki", (done) => { const entityInsert = { PartitionKey: "part1", RowKey: "row5", @@ -319,7 +319,7 @@ describe("table Entity APIs test", () => { ); }); - it("Insert or Replace (upsert) on an Entity that does not exist, @loki", done => { + it("Insert or Replace (upsert) on an Entity that does not exist, @loki", (done) => { requestOverride.headers = { Prefer: "return-content", accept: "application/json;odata=fullmetadata" @@ -344,7 +344,7 @@ describe("table Entity APIs test", () => { ); }); - it("Insert or Replace (upsert) on an Entity that exists, @loki", done => { + it("Insert or Replace (upsert) on an Entity that exists, @loki", (done) => { requestOverride.headers = { Prefer: "return-content", accept: "application/json;odata=fullmetadata" @@ -369,7 +369,7 @@ describe("table Entity APIs test", () => { ); }); - it("Insert or Merge on an Entity that exists, @loki", done => { + it("Insert or Merge on an Entity that exists, @loki", (done) => { const entityInsert = { PartitionKey: "part1", RowKey: "merge1", @@ -412,7 +412,7 @@ describe("table Entity APIs test", () => { ); }); - it("Insert or Merge on an Entity that does not exist, @loki", done => { + it("Insert or Merge on an Entity that does not exist, @loki", (done) => { requestOverride.headers = { Prefer: "return-content", accept: "application/json;odata=fullmetadata" diff --git a/tests/table/sas.test.ts b/tests/table/sas.test.ts index 29cfdedf9..0e3475ebb 100644 --- a/tests/table/sas.test.ts +++ b/tests/table/sas.test.ts @@ -59,7 +59,7 @@ describe("Shared Access Signature (SAS) authentication", () => { await server.clean(); }); - it("insertEntity with Query permission should not work @loki", done => { + it("insertEntity with Query permission should not work @loki", (done) => { const expiry = new Date(); expiry.setMinutes(expiry.getMinutes() + 5); // Skip clock skew with server @@ -83,7 +83,7 @@ describe("Shared Access Signature (SAS) authentication", () => { }); }); - it("insertEntity with Add permission should work @loki", done => { + it("insertEntity with Add permission should work @loki", (done) => { const expiry = new Date(); expiry.setMinutes(expiry.getMinutes() + 5); // Skip clock skew with server @@ -104,7 +104,7 @@ describe("Shared Access Signature (SAS) authentication", () => { }); }); - it("insertEntity Add permission should work @loki", done => { + it("insertEntity Add permission should work @loki", (done) => { const sasService = getSasService({ Permissions: TableSASPermission.Add, ...sasPeriod(-1, 5) @@ -122,7 +122,7 @@ describe("Shared Access Signature (SAS) authentication", () => { }); }); - it("insertEntity expired Add permission should not work @loki", done => { + it("insertEntity expired Add permission should not work @loki", (done) => { const sasService = getSasService({ Permissions: TableSASPermission.Add, ...sasPeriod(-10, -5) @@ -140,7 +140,7 @@ describe("Shared Access Signature (SAS) authentication", () => { }); }); - it("deleteEntity with Delete permission should work @loki", done => { + it("deleteEntity with Delete permission should work @loki", (done) => { const sasService = getSasService({ Permissions: TableSASPermission.Delete, ...sasPeriod(0, 5) @@ -158,7 +158,7 @@ describe("Shared Access Signature (SAS) authentication", () => { }); }); - it("deleteEntity with Add permission should not work @loki", done => { + it("deleteEntity with Add permission should not work @loki", (done) => { const sasService = getSasService({ Permissions: TableSASPermission.Add, ...sasPeriod(0, 5) @@ -176,7 +176,7 @@ describe("Shared Access Signature (SAS) authentication", () => { }); }); - it("Update an Entity that exists, @loki", done => { + it("Update an Entity that exists, @loki", (done) => { const sasService = getSasService({ Permissions: TableSASPermission.Add + TableSASPermission.Update, ...sasPeriod(0, 5) @@ -213,7 +213,7 @@ describe("Shared Access Signature (SAS) authentication", () => { ); }); - it("Update an Entity without update permission, @loki", done => { + it("Update an Entity without update permission, @loki", (done) => { const sasService = getSasService({ Permissions: TableSASPermission.Add, ...sasPeriod(0, 5) @@ -234,7 +234,7 @@ describe("Shared Access Signature (SAS) authentication", () => { ); }); - it("Update an Entity that does not exist, @loki", done => { + it("Update an Entity that does not exist, @loki", (done) => { const sasService = getSasService({ Permissions: TableSASPermission.Update, ...sasPeriod(0, 5) @@ -246,7 +246,7 @@ describe("Shared Access Signature (SAS) authentication", () => { (updateError, updateResult, updateResponse) => { const castUpdateStatusCode = (updateError as StorageError).statusCode; if (updateError) { - assert.equal(castUpdateStatusCode, 409); + assert.equal(castUpdateStatusCode, 404); done(); } else { assert.fail("Test failed to throw the right Error" + updateError); From aa6cba7904e0c6e147bf1f932981776a09d7d059 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Mon, 16 Nov 2020 16:52:00 +0800 Subject: [PATCH 30/57] Add support for X-HTTP-METHOD (#625) * Return 404 instead 409 when entity doesn't exist. Fix #621 * Compatible query entity with empty pk & rk. Fix #620 * Add support for X-HTTP-METHOD --- src/blob/generated/IRequest.ts | 1 + .../middleware/dispatch.middleware.ts | 21 +++++++++++++++---- src/queue/generated/IRequest.ts | 1 + .../middleware/dispatch.middleware.ts | 20 +++++++++++++++--- src/table/generated/IRequest.ts | 1 + .../middleware/dispatch.middleware.ts | 20 +++++++++++++++--- 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/blob/generated/IRequest.ts b/src/blob/generated/IRequest.ts index df39dd0ad..c281157bf 100644 --- a/src/blob/generated/IRequest.ts +++ b/src/blob/generated/IRequest.ts @@ -7,6 +7,7 @@ export type HttpMethod = | "CONNECT" | "OPTIONS" | "TRACE" + | "MERGE" | "PATCH"; export default interface IRequest { diff --git a/src/blob/generated/middleware/dispatch.middleware.ts b/src/blob/generated/middleware/dispatch.middleware.ts index 26cf7f30c..5e933b8de 100644 --- a/src/blob/generated/middleware/dispatch.middleware.ts +++ b/src/blob/generated/middleware/dispatch.middleware.ts @@ -90,11 +90,24 @@ function isRequestAgainstOperation( return [false, metConditionsNum]; } + const xHttpMethod = req.getHeader("X-HTTP-Method"); + let method = req.getMethod(); + if (xHttpMethod && xHttpMethod.length > 0) { + const value = xHttpMethod.trim(); + if ( + value === "GET" || + value === "MERGE" || + value === "PATCH" || + value === "DELETE" + ) { + method = value; + } + } + // Validate HTTP method - if (req.getMethod() !== spec.httpMethod) { + if (method !== spec.httpMethod) { return [false, metConditionsNum++]; } - // Validate URL path const path = spec.path ? spec.path.startsWith("/") @@ -123,7 +136,7 @@ function isRequestAgainstOperation( if ( queryParameter.mapper.type.name === "Enum" && - queryParameter.mapper.type.allowedValues.findIndex(val => { + queryParameter.mapper.type.allowedValues.findIndex((val) => { return val === queryValue; }) < 0 ) { @@ -153,7 +166,7 @@ function isRequestAgainstOperation( if ( headerParameter.mapper.type.name === "Enum" && - headerParameter.mapper.type.allowedValues.findIndex(val => { + headerParameter.mapper.type.allowedValues.findIndex((val) => { return val === headerValue; }) < 0 ) { diff --git a/src/queue/generated/IRequest.ts b/src/queue/generated/IRequest.ts index df39dd0ad..c281157bf 100644 --- a/src/queue/generated/IRequest.ts +++ b/src/queue/generated/IRequest.ts @@ -7,6 +7,7 @@ export type HttpMethod = | "CONNECT" | "OPTIONS" | "TRACE" + | "MERGE" | "PATCH"; export default interface IRequest { diff --git a/src/queue/generated/middleware/dispatch.middleware.ts b/src/queue/generated/middleware/dispatch.middleware.ts index b287f82e8..f447ade33 100644 --- a/src/queue/generated/middleware/dispatch.middleware.ts +++ b/src/queue/generated/middleware/dispatch.middleware.ts @@ -90,8 +90,22 @@ function isRequestAgainstOperation( return [false, metConditionsNum]; } + const xHttpMethod = req.getHeader("X-HTTP-Method"); + let method = req.getMethod(); + if (xHttpMethod && xHttpMethod.length > 0) { + const value = xHttpMethod.trim(); + if ( + value === "GET" || + value === "MERGE" || + value === "PATCH" || + value === "DELETE" + ) { + method = value; + } + } + // Validate HTTP method - if (req.getMethod() !== spec.httpMethod) { + if (method !== spec.httpMethod) { return [false, metConditionsNum++]; } @@ -123,7 +137,7 @@ function isRequestAgainstOperation( if ( queryParameter.mapper.type.name === "Enum" && - queryParameter.mapper.type.allowedValues.findIndex(val => { + queryParameter.mapper.type.allowedValues.findIndex((val) => { return val === queryValue; }) < 0 ) { @@ -153,7 +167,7 @@ function isRequestAgainstOperation( if ( headerParameter.mapper.type.name === "Enum" && - headerParameter.mapper.type.allowedValues.findIndex(val => { + headerParameter.mapper.type.allowedValues.findIndex((val) => { return val === headerValue; }) < 0 ) { diff --git a/src/table/generated/IRequest.ts b/src/table/generated/IRequest.ts index df39dd0ad..c281157bf 100644 --- a/src/table/generated/IRequest.ts +++ b/src/table/generated/IRequest.ts @@ -7,6 +7,7 @@ export type HttpMethod = | "CONNECT" | "OPTIONS" | "TRACE" + | "MERGE" | "PATCH"; export default interface IRequest { diff --git a/src/table/generated/middleware/dispatch.middleware.ts b/src/table/generated/middleware/dispatch.middleware.ts index b287f82e8..f447ade33 100644 --- a/src/table/generated/middleware/dispatch.middleware.ts +++ b/src/table/generated/middleware/dispatch.middleware.ts @@ -90,8 +90,22 @@ function isRequestAgainstOperation( return [false, metConditionsNum]; } + const xHttpMethod = req.getHeader("X-HTTP-Method"); + let method = req.getMethod(); + if (xHttpMethod && xHttpMethod.length > 0) { + const value = xHttpMethod.trim(); + if ( + value === "GET" || + value === "MERGE" || + value === "PATCH" || + value === "DELETE" + ) { + method = value; + } + } + // Validate HTTP method - if (req.getMethod() !== spec.httpMethod) { + if (method !== spec.httpMethod) { return [false, metConditionsNum++]; } @@ -123,7 +137,7 @@ function isRequestAgainstOperation( if ( queryParameter.mapper.type.name === "Enum" && - queryParameter.mapper.type.allowedValues.findIndex(val => { + queryParameter.mapper.type.allowedValues.findIndex((val) => { return val === queryValue; }) < 0 ) { @@ -153,7 +167,7 @@ function isRequestAgainstOperation( if ( headerParameter.mapper.type.name === "Enum" && - headerParameter.mapper.type.allowedValues.findIndex(val => { + headerParameter.mapper.type.allowedValues.findIndex((val) => { return val === headerValue; }) < 0 ) { From 41bee845443b54d61972286c3447704ac18ecee7 Mon Sep 17 00:00:00 2001 From: Hannes Schulz Date: Sun, 7 Feb 2021 10:41:02 +0100 Subject: [PATCH 31/57] add prepare script to facilitate installation from github (#681) * add prepare script to facilitate installation from github * adapt Dockerfile since prepare step is subsumed by install step now --- Dockerfile | 11 ++++------- package.json | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index b5fb5e8dc..2f48f8b42 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,13 +7,12 @@ WORKDIR /opt/azurite # Install dependencies first COPY *.json LICENSE NOTICE.txt ./ -RUN npm config set unsafe-perm=true && \ - npm ci # Copy the source code and build the app COPY src ./src COPY tests ./tests -RUN npm run build && \ +RUN npm config set unsafe-perm=true && \ + npm ci && \ npm install -g --loglevel verbose @@ -31,12 +30,10 @@ VOLUME [ "/data" ] COPY package*.json LICENSE NOTICE.txt ./ -RUN npm config set unsafe-perm=true && \ - npm ci - COPY --from=builder /opt/azurite/dist/ dist/ -RUN npm install -g --loglevel verbose +RUN npm config set unsafe-perm=true && \ + npm install -g --loglevel verbose # Blob Storage Port EXPOSE 10000 diff --git a/package.json b/package.json index 3089719df..5e697c21f 100644 --- a/package.json +++ b/package.json @@ -213,6 +213,7 @@ "docker:build:internal": "npm run docker:prebuild && cross-var docker build --no-cache --rm -f \"Dockerfile\" -t xstoreazurite.azurecr.io/internal/azure-storage/azurite:$npm_package_version . && cross-var docker tag xstoreazurite.azurecr.io/internal/azure-storage/azurite:$npm_package_version xstoreazurite.azurecr.io/internal/azure-storage/azurite:latest", "docker:publish": "cross-var docker push xstoreazurite.azurecr.io/public/azure-storage/azurite:$npm_package_version", "docker:publish:internal": "cross-var docker push xstoreazurite.azurecr.io/internal/azure-storage/azurite:$npm_package_version", + "prepare": "npm run build", "build": "tsc", "build:autorest:debug": "autorest ./swagger/blob.md --typescript --typescript.debugger --use=E:/GitHub/XiaoningLiu/autorest.typescript.server", "build:autorest:blob": "autorest ./swagger/blob.md --typescript --use=S:/GitHub/XiaoningLiu/autorest.typescript.server", From 7ffe161cdb8be3976f1a64c1eb0c12e59304b77d Mon Sep 17 00:00:00 2001 From: Marek Strejczek Date: Wed, 10 Feb 2021 03:29:54 +0100 Subject: [PATCH 32/57] Etag returned by Table Storage follows Azure format now (#697) * Etag returned by Table Storage follows Azure format now * Table Entity etag uses datetime aligned with entity lastmodifiedtime and with precisionupped to 7 millisecond digits Co-authored-by: Marek Strejczek --- src/common/utils/utils.ts | 5 +++++ src/table/handlers/TableHandler.ts | 8 ++++---- tests/table/apis/table.entity.test.ts | 5 +++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/common/utils/utils.ts b/src/common/utils/utils.ts index bf0a8ad41..8d0ef4e8a 100644 --- a/src/common/utils/utils.ts +++ b/src/common/utils/utils.ts @@ -60,6 +60,11 @@ export function newEtag(): string { ); } +export function newTableEntityEtag(startTime: Date): string { + // Etag as returned by Table Storage should match W/"datetime''" + return "W/\"datetime'" + truncatedISO8061Date(startTime, true) + "'\""; +} + /** * Generates a hash signature for an HTTP request or for a SAS. * diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index d65543619..b9401aee3 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -1,5 +1,5 @@ import BufferStream from "../../common/utils/BufferStream"; -import { newEtag } from "../../common/utils/utils"; +import { newTableEntityEtag } from "../../common/utils/utils"; import TableStorageContext from "../context/TableStorageContext"; import { NormalizedEntity } from "../entity/NormalizedEntity"; import NotImplementedError from "../errors/NotImplementedError"; @@ -178,7 +178,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { RowKey: options.tableEntityProperties.RowKey, properties: options.tableEntityProperties, lastModifiedTime: context.startTime!, - eTag: newEtag() + eTag: newTableEntityEtag(context.startTime!) }; let nomarlizedEntity; @@ -279,7 +279,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { throw StorageErrorFactory.getPreconditionFailed(context); } - const eTag = newEtag(); + const eTag = newTableEntityEtag(context.startTime!); // Entity, which is used to update an existing entity const entity: Entity = { @@ -349,7 +349,7 @@ export default class TableHandler extends BaseHandler implements ITableHandler { ); } - const eTag = newEtag(); + const eTag = newTableEntityEtag(context.startTime!); const entity: Entity = { PartitionKey: partitionKey, diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 4468eaf9a..058d279e5 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -75,6 +75,11 @@ describe("table Entity APIs test", () => { }; tableService.insertEntity(tableName, entity, (error, result, response) => { assert.equal(response.statusCode, 201); + assert.ok( + response.headers?.etag.match( + "W/\"datetime'\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{7}Z'\"" + ) + ); done(); }); }); From 98d14a2eaa9b44bfd0bce7f0d1fe42c21ead8179 Mon Sep 17 00:00:00 2001 From: shoaibahmd1 <72392811+shoaibahmd1@users.noreply.github.com> Date: Wed, 24 Mar 2021 12:35:45 +0500 Subject: [PATCH 33/57] 704 allow empty rowkey (#711) * Allows empty rowkey * removes debugging statements * Added test case for empty rowkey * test case for missing rowkey added * removed test case for missing RowKey in table * using triple operator in insertEntity * Added test case to retrieve entity with empty RowKey --- ChangeLog.md | 4 ++ src/table/handlers/TableHandler.ts | 3 +- tests/table/apis/table.entity.test.ts | 62 +++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 06cf5f2ee..0eab20d70 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,6 +4,10 @@ ## Upcoming Release +Table: + +- Allow empty RowKey in an entity. + ## 2020.11 Version 3.9.0-table-alpha.1 Table: diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index b9401aee3..09c7b09d4 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -168,7 +168,8 @@ export default class TableHandler extends BaseHandler implements ITableHandler { if ( !options.tableEntityProperties || !options.tableEntityProperties.PartitionKey || - !options.tableEntityProperties.RowKey + (!options.tableEntityProperties.RowKey && + options.tableEntityProperties.RowKey !== "") ) { throw StorageErrorFactory.getPropertiesNeedValue(context); } diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 058d279e5..1caecf709 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -84,6 +84,68 @@ describe("table Entity APIs test", () => { }); }); + // Simple test in here until we have the full set checked in, as we need + // a starting point for delete and query entity APIs + it("Should insert new Entity with empty RowKey, @loki", (done) => { + // https://docs.microsoft.com/en-us/rest/api/storageservices/insert-entity + const entity = { + PartitionKey: "part1", + RowKey: "", + myValue: "value1" + }; + tableService.insertEntity(tableName, entity, (error, result, response) => { + assert.equal(response.statusCode, 201); + assert.ok( + response.headers?.etag.match( + "W/\"datetime'\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{7}Z'\"" + ) + ); + done(); + }); + }); + + it("Should retrieve entity with empty RowKey, @loki", (done) => { + const entityInsert = { + PartitionKey: "part2", + RowKey: "", + myValue: "value1" + }; + tableService.insertEntity( + tableName, + entityInsert, + (insertError, insertResult, insertResponse) => { + if (!insertError) { + var query = new Azure.TableQuery() + .where("PartitionKey == ?", "part2") + .and("myValue == ?", "value1"); + + tableService.queryEntities( + tableName, + query, + null, + null, + (queryError, queryResult, queryResponse) => { + if (!queryError) { + if (queryResult.entries && queryResult.entries.length > 0) { + assert.equal(queryResponse.statusCode, 200); + done(); + } else { + assert.fail("Test failed to retrieve the entity."); + } + } else { + assert.ifError(queryError); + done(); + } + } + ); + } else { + assert.ifError(insertError); + done(); + } + } + ); + }); + it("Should delete an Entity using etag wildcard, @loki", (done) => { // https://docs.microsoft.com/en-us/rest/api/storageservices/delete-entity1 const entity = { From 42ff12135c8817acfb0725757207fd71fb63e70f Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Wed, 24 Mar 2021 10:15:19 +0100 Subject: [PATCH 34/57] Table Batch / Entity Group Transactions v1 (#691) * Initial Entity Group Transactions / Table Batch implementation * updated table entity tests with tests for table batch * added set of batch apis * updated serialization and added unit test for serializer * added serialization unit tests * Initial support for Azure Durable Functions & Azure Logic Apps --- package-lock.json | 5 + package.json | 1 + src/common/batch/BatchOperation.ts | 31 + src/common/batch/BatchRequest.ts | 198 ++++++ src/common/batch/BatchRequestHeaders.ts | 142 +++++ src/common/batch/BatchSerialization.ts | 65 ++ .../BatchTableDeleteEntityOptionalParams.ts | 68 +++ .../BatchTableInsertEntityOptionalParams.ts | 46 ++ .../BatchTableMergeEntityOptionalParams.ts | 46 ++ .../BatchTableQueryEntitiesOptionalParams.ts | 46 ++ ...iesWithPartitionAndRowKeyOptionalParams.ts | 48 ++ .../BatchTableUpdateEntityOptionalParams.ts | 46 ++ src/table/batch/IOptionalParams.ts | 58 ++ src/table/batch/TableBatchOperation.ts | 7 + src/table/batch/TableBatchOrchestrator.ts | 536 ++++++++++++++++ src/table/batch/TableBatchSerialization.ts | 575 ++++++++++++++++++ src/table/batch/TableBatchUtils.ts | 23 + src/table/generated/artifacts/models.ts | 138 +++-- src/table/handlers/TableHandler.ts | 74 ++- .../persistence/LokiTableMetadataStore.ts | 24 +- tests/table/apis/table.entity.test.ts | 537 +++++++++++++++- .../table/unit/deserialization.unit.tests.ts | 345 +++++++++++ .../mock.request.serialization.strings.ts | 72 +++ .../mock.response.serialization.strings.ts | 54 ++ ...ck.serialization.batchoperation.factory.ts | 75 +++ ...mock.serialization.batchrequest.factory.ts | 89 +++ tests/table/unit/serialization.unit.tests.ts | 116 ++++ 27 files changed, 3345 insertions(+), 120 deletions(-) create mode 100644 src/common/batch/BatchOperation.ts create mode 100644 src/common/batch/BatchRequest.ts create mode 100644 src/common/batch/BatchRequestHeaders.ts create mode 100644 src/common/batch/BatchSerialization.ts create mode 100644 src/table/batch/BatchTableDeleteEntityOptionalParams.ts create mode 100644 src/table/batch/BatchTableInsertEntityOptionalParams.ts create mode 100644 src/table/batch/BatchTableMergeEntityOptionalParams.ts create mode 100644 src/table/batch/BatchTableQueryEntitiesOptionalParams.ts create mode 100644 src/table/batch/BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams.ts create mode 100644 src/table/batch/BatchTableUpdateEntityOptionalParams.ts create mode 100644 src/table/batch/IOptionalParams.ts create mode 100644 src/table/batch/TableBatchOperation.ts create mode 100644 src/table/batch/TableBatchOrchestrator.ts create mode 100644 src/table/batch/TableBatchSerialization.ts create mode 100644 src/table/batch/TableBatchUtils.ts create mode 100644 tests/table/unit/deserialization.unit.tests.ts create mode 100644 tests/table/unit/mock.request.serialization.strings.ts create mode 100644 tests/table/unit/mock.response.serialization.strings.ts create mode 100644 tests/table/unit/mock.serialization.batchoperation.factory.ts create mode 100644 tests/table/unit/mock.serialization.batchrequest.factory.ts create mode 100644 tests/table/unit/serialization.unit.tests.ts diff --git a/package-lock.json b/package-lock.json index ee9266bd8..eff00cc96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6172,6 +6172,11 @@ } } }, + "to-readable-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz", + "integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==" + }, "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", diff --git a/package.json b/package.json index 5e697c21f..e68810993 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "rimraf": "^2.6.3", "sequelize": "^6.3.0", "tedious": "^9.2.1", + "to-readable-stream": "^2.1.0", "tslib": "^1.9.3", "uri-templates": "^0.2.0", "uuid": "^3.3.2", diff --git a/src/common/batch/BatchOperation.ts b/src/common/batch/BatchOperation.ts new file mode 100644 index 000000000..6d3d1dd23 --- /dev/null +++ b/src/common/batch/BatchOperation.ts @@ -0,0 +1,31 @@ +import { HttpMethod } from "../../blob/generated/IRequest"; + +export enum BatchType { + blob = "blob", + table = "table" +} + +/** + * A container for batch operations + * + * @export + * @class BatchOperation + */ +export default class BatchOperation { + public rawHeaders: string[]; + public protocol?: string; + public batchType: BatchType; + public httpMethod?: HttpMethod; + public parameters?: string; + public uri?: string; + public path?: string; + public jsonRequestBody?: string; // maybe we want the entity operation to be stored in a parsed format? + public constructor(_batchType: BatchType, headers: string) { + this.batchType = _batchType; + const dirtyHeaderArray = headers.split("\n"); + // filter out the blanks + this.rawHeaders = dirtyHeaderArray.filter( + (candidate) => candidate.search(/\S/) < 1 + ); + } +} diff --git a/src/common/batch/BatchRequest.ts b/src/common/batch/BatchRequest.ts new file mode 100644 index 000000000..d8aee3cf7 --- /dev/null +++ b/src/common/batch/BatchRequest.ts @@ -0,0 +1,198 @@ +import { Stream } from "stream"; +import IRequest, { HttpMethod } from "../../table/generated/IRequest"; +import BatchOperation from "./BatchOperation"; +import BatchRequestHeaders from "./BatchRequestHeaders"; +import * as Models from "../../table/generated/artifacts/models"; +import BatchTableUpdateEntityOptionalParams from "../../table/batch/BatchTableUpdateEntityOptionalParams"; +import BatchTableDeleteEntityOptionalParams from "../../table/batch/BatchTableDeleteEntityOptionalParams"; +import IOptionalParams from "../../table/batch/IOptionalParams"; + +/* + * Represents a request in the context of batch operations. + * ToDo: Requires validation against all operation types + * Currently several funcitons of the interface are not implemented + * @export + * @class BatchRequest + * @implements {IRequest} + */ +export default class BatchRequest implements IRequest { + public response?: any; + private headers: BatchRequestHeaders; + private batchOperation: BatchOperation; + public contentID: number | undefined; + public constructor(batchOperation: BatchOperation) { + this.batchOperation = batchOperation; + this.headers = new BatchRequestHeaders(batchOperation.rawHeaders); + // set default params, due to our processing logic + this.params = new BatchTableUpdateEntityOptionalParams(); + } + + // ToDo: This should really be using an interface. + // refactor once the basic logic is working + // | BatchTableDeleteEntityOptionalParams + // | BatchTableUpdateEntityOptionalParams + // | BatchTableMergeEntityOptionalParams + // | BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams + // | BatchTableQueryEntitiesOptionalParams + // | BatchTableInsertEntityOptionalParams; + public params: IOptionalParams; + + // ingests the optional params for a batch request, and sets these + // based on the type of operation and headers present on an + // individual request + public ingestOptionalParams(params: IOptionalParams) { + this.params = params; + // need to compare headers to option params and set accordingly + if (this.getHeader("x-ms-client-request-id") !== undefined) { + this.params.requestId = this.getHeader("x-ms-client-request-id"); + } + + // Theoretically, this Enum is redundant, and used across all table + // optional param models, thinking that we only need to use the 1, + // the code generator is however differentiating across all of them + // as distinct + if (this.getHeader("maxdataserviceversion")?.includes("3.0")) { + this.params.dataServiceVersion = + Models.DataServiceVersion4.ThreeFullStopZero; + } + // TableDeleteEntityOptionalParams is the only interface without a body + // I instantiate the batch class to enable this check and the other + // interface acrobatics needed for batch processing + const body = this.getBody(); + if ( + body != null && + body !== "" && + !(this.params instanceof BatchTableDeleteEntityOptionalParams) + ) { + this.params.tableEntityProperties = JSON.parse(body); + } + + // set request timeout + // https://docs.microsoft.com/en-us/rest/api/storageservices/setting-timeouts-for-table-service-operations + + // set responsePreference + + // set queryOptions + // https://docs.microsoft.com/en-us/rest/api/storageservices/payload-format-for-table-service-operations + const options: Models.QueryOptions = new Object() as Models.QueryOptions; + // format + // set payload options + if (this.getHeader("accept")?.includes("minimalmeta")) { + options.format = + Models.OdataMetadataFormat.Applicationjsonodataminimalmetadata; + } else if (this.getHeader("accept")?.includes("fullmeta")) { + options.format = + Models.OdataMetadataFormat.Applicationjsonodatafullmetadata; + } else { + options.format = + Models.OdataMetadataFormat.Applicationjsonodatanometadata; + } + // top + // select + // filter + this.params.queryOptions = options; + } + + public getMethod(): HttpMethod { + if (this.batchOperation.httpMethod != null) { + return this.batchOperation.httpMethod; + } else { + throw new Error("httpMethod invalid on batch operation"); + } + } + + public getUrl(): string { + // ToDo: is this a valid assumption for the batch API? + // ToDo: here we also assume https, which is also not true... + // we need to parse this from the request + // return `https://${this.accountName}.${this.batchOperation.batchType}.core.windows.net/$batch`; + // in delete, it seems that we actuall expect the full uri + if (this.batchOperation.uri != null && this.batchOperation.path != null) { + return this.batchOperation.uri; + // this substring is not needed. + // .substring( + // 0, + // this.batchOperation.uri.length - this.batchOperation.path.length + // ); + } else { + throw new Error("uri or path null when calling getUrl on BatchRequest"); + } + } + + public getEndpoint(): string { + throw new Error("Method not implemented."); + } + + public getPath(): string { + if (this.batchOperation.path != null) { + return this.batchOperation.path; + } else { + throw new Error("path null when calling getPath on BatchRequest"); + } + } + + public getBodyStream(): NodeJS.ReadableStream { + if (this.batchOperation.jsonRequestBody != null) { + return Stream.Readable.from(this.batchOperation.jsonRequestBody); + } else { + throw new Error("body null when calling getBodyStream on BatchRequest"); + } + } + + public setBody(body: string | undefined): IRequest { + throw new Error("Method not implemented."); + } + + public getBody(): string | undefined { + if (this.batchOperation.jsonRequestBody != null) { + return this.batchOperation.jsonRequestBody; + } else { + throw new Error("body null when calling getBody on BatchRequest"); + } + } + + public getHeader(field: string): string | undefined { + return this.headers.header(field); + } + + public getHeaders(): { [header: string]: string | string[] | undefined } { + throw new Error("Method not implemented."); + } + + public getRawHeaders(): string[] { + return this.batchOperation.rawHeaders; + } + + public getQuery(key: string): string | undefined { + switch (key) { + case "$format": + return this.params.queryOptions?.format; + case "$top": + return this.params.queryOptions?.top?.toLocaleString(); + case "$select": + return this.params.queryOptions?.select; + case "$filter": + return this.params.queryOptions?.filter; + default: + break; + } + throw new Error("unknown query options type."); + } + + public getProtocol(): string { + if ( + this.batchOperation.protocol !== null && + this.batchOperation.protocol !== undefined + ) { + return this.batchOperation.protocol; + } else { + // try extract protocol + const protocolMatch = this.getUrl().match(/https?/); + if (protocolMatch !== null && protocolMatch!.length > 0) { + this.batchOperation.protocol = protocolMatch[0]; + return this.batchOperation.protocol; + } + throw new Error("protocol null when calling getProtocol on BatchRequest"); + } + } +} diff --git a/src/common/batch/BatchRequestHeaders.ts b/src/common/batch/BatchRequestHeaders.ts new file mode 100644 index 000000000..c3b245a22 --- /dev/null +++ b/src/common/batch/BatchRequestHeaders.ts @@ -0,0 +1,142 @@ +/** + * Provides access to headers for batch requests. + * As requests in an entity group transaction have different headers per + * transaction, and these need to be handled separately to the + * outer request envelope. + * + * @export + * @class BatchRequestHeaders + */ +export default class BatchRequestHeaders { + public constructor(headers: string[]) { + this.rawHeaders = headers; + this.createDictFromRawHeaders(); + } + private rawHeaders: string[]; + private headerItems: { [index: string]: string } = {}; + private headerCount: number = 0; + + /** + * Returns the raw headers as a string array + * + * @return {*} + * @memberof BatchRequestHeaders + */ + public getRawHeaders() { + return this.rawHeaders; + } + + /** + * Checks for existence of a header + * + * @param {string} key + * @return {*} {boolean} + * @memberof BatchRequestHeaders + */ + public containsHeader(key: string): boolean { + return this.headerItems.hasOwnProperty(key); + } + + /** + * The count of headers + * + * @return {*} {number} + * @memberof BatchRequestHeaders + */ + public count(): number { + return this.headerCount; + } + + /** + * Add a header to the header items + * + * @param {string} key + * @param {string} value + * @memberof BatchRequestHeaders + */ + public add(key: string, value: string) { + if (!this.headerItems.hasOwnProperty(key)) this.headerCount++; + + this.headerItems[key] = value; + } + + /** + * Remove a header from the header items + * + * @param {string} key + * @return {*} {string} + * @memberof BatchRequestHeaders + */ + public remove(key: string): string { + const val = this.headerItems[key]; + delete this.headerItems[key]; + this.headerCount--; + return val; + } + + /** + * Returns the header value based on a lower case lookup of the key + * + * @param {string} key + * @return {*} {string} + * @memberof BatchRequestHeaders + */ + public header(key: string): string { + return this.headerItems[key.toLocaleLowerCase()]; + } + + /** + * The header keys as a string array + * + * @return {*} {string[]} + * @memberof BatchRequestHeaders + */ + public headerKeys(): string[] { + const headers: string[] = []; + + for (const prop in this.headerItems) { + if (this.headerItems.hasOwnProperty(prop)) { + headers.push(prop); + } + } + + return headers; + } + + /** + * Header values as a string array + * + * @return {*} {string[]} + * @memberof BatchRequestHeaders + */ + public headerValues(): string[] { + const values: string[] = []; + + for (const prop in this.headerItems) { + if (this.headerItems.hasOwnProperty(prop)) { + values.push(this.headerItems[prop]); + } + } + + return values; + } + + /** + * Creates the dictionary to allow key value lookups on the headers + * + * @private + * @memberof BatchRequestHeaders + */ + private createDictFromRawHeaders(): void { + this.rawHeaders.forEach((rawheader) => { + if (rawheader != null) { + const headerMatch = rawheader.match(/(\S+)(:\s?)(\S+)/); + if (headerMatch == null && rawheader.length > 2) { + this.add(rawheader, ""); + } else if (headerMatch != null) { + this.add(headerMatch[1].toLocaleLowerCase(), headerMatch[3]); + } + } + }); + } +} diff --git a/src/common/batch/BatchSerialization.ts b/src/common/batch/BatchSerialization.ts new file mode 100644 index 000000000..f653addb4 --- /dev/null +++ b/src/common/batch/BatchSerialization.ts @@ -0,0 +1,65 @@ +import { exception } from "console"; +import { StorageError } from "../../blob/generated/artifacts/mappers"; + +/** + * Base Batch serialization class. + * Contains shared logic for batch serialization. + * ToDo: Make these util functions static or aggregate this logic into one of the other + * batch classes + * + * @export + * @param {string} batchBoundary + * @param {string} changesetBoundary + */ +export class BatchSerialization { + public batchBoundary: string = ""; + public changesetBoundary: string = ""; + public lineEnding: string = ""; + + public extractBatchBoundary(batchRequestsString: string): void { + const batchBoundaryMatch = batchRequestsString.match( + // prettier-ignore + /--batch_(\w+-?)+/ + ); + if (null != batchBoundaryMatch) { + this.batchBoundary = batchBoundaryMatch[0]; + } else { + throw exception("no batch boiundary found in request"); + } + } + + // ToDo: improve RegEx, as not sure if spec allows for use of other + // change set boundary styles (such as boundary=blahblahblah) + // have tried to make as generic as possible + public extractChangeSetBoundary(batchRequestsString: string): void { + let subChangeSetPrefixMatches = batchRequestsString.match( + /(boundary=)+(\w+_?(\w+-?)+)/ + ); + + if (subChangeSetPrefixMatches != null) { + this.changesetBoundary = subChangeSetPrefixMatches[2]; + } else { + // we need to see if this is a single query batch operation + // whose format is different! (as we only support a single query per batch) + // ToDo: do we need to check for GET HTTP verb? + subChangeSetPrefixMatches = batchRequestsString.match(/(--batch_\w+)/); + if (subChangeSetPrefixMatches != null) { + this.changesetBoundary = subChangeSetPrefixMatches[1]; + } else { + throw StorageError; + } + } + } + + public extractLineEndings(batchRequestsString: string): void { + const lineEndingMatch = batchRequestsString.match( + // prettier-ignore + /\r?\n+/ + ); + if (lineEndingMatch != null) { + this.lineEnding = lineEndingMatch[0]; + } else { + throw StorageError; + } + } +} diff --git a/src/table/batch/BatchTableDeleteEntityOptionalParams.ts b/src/table/batch/BatchTableDeleteEntityOptionalParams.ts new file mode 100644 index 000000000..4a615a260 --- /dev/null +++ b/src/table/batch/BatchTableDeleteEntityOptionalParams.ts @@ -0,0 +1,68 @@ +import { + DataServiceVersion7, + QueryOptions, + ResponseFormat, + TableDeleteEntityOptionalParams +} from "../generated/artifacts/models"; +import IOptionalParams from "./IOptionalParams"; + +/** + * Batch Table Delete Entity Optional Params + * + * @export + * @class BatchTableDeleteEntityOptionalParams + * @implements {TableDeleteEntityOptionalParams} + */ +export default class BatchTableDeleteEntityOptionalParams + implements TableDeleteEntityOptionalParams, IOptionalParams { + /** + * The timeout parameter is expressed in seconds. + * + * @type {number} + * @memberof BatchTableDeleteEntityOptionalParams + */ + public timeout?: number; + + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + * + * @type {string} + * @memberof BatchTableDeleteEntityOptionalParams + */ + public requestId?: string; + + /** + * Specifies the data service version. Possible values include: '3.0' + * + * @type {DataServiceVersion7} + * @memberof BatchTableDeleteEntityOptionalParams + */ + public dataServiceVersion?: DataServiceVersion7; + + /** + * The properties for the table entity. + * + * @type {{ [propertyName: string]: any }} + * @memberof BatchTableDeleteEntityOptionalParams + */ + public tableEntityProperties?: { [propertyName: string]: any }; + + /** + * Specifies whether the response should include the inserted entity in the payload. Possible + * values are return-no-content and return-content. Possible values include: 'return-no-content', + * 'return-content' + * + * @type {ResponseFormat} + * @memberof BatchTableDeleteEntityOptionalParams + */ + public responsePreference?: ResponseFormat; + + /** + * Additional parameters for the operation + * + * @type {QueryOptions} + * @memberof BatchTableDeleteEntityOptionalParams + */ + public queryOptions?: QueryOptions; +} diff --git a/src/table/batch/BatchTableInsertEntityOptionalParams.ts b/src/table/batch/BatchTableInsertEntityOptionalParams.ts new file mode 100644 index 000000000..0663cc724 --- /dev/null +++ b/src/table/batch/BatchTableInsertEntityOptionalParams.ts @@ -0,0 +1,46 @@ +import { + DataServiceVersion9, + QueryOptions, + ResponseFormat, + TableInsertEntityOptionalParams +} from "../generated/artifacts/models"; +import IOptionalParams from "./IOptionalParams"; + +/** + * Batch Table Insert Entity Optional Params + * + * @export + * @class BatchTableInsertEntityOptionalParams + * @implements {TableInsertEntityOptionalParams} + * @implements {IOptionalParams} + */ +export default class BatchTableInsertEntityOptionalParams + implements TableInsertEntityOptionalParams, IOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + public timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + public requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + public dataServiceVersion?: DataServiceVersion9; + /** + * The properties for the table entity. + */ + public tableEntityProperties?: { [propertyName: string]: any }; + /** + * Specifies whether the response should include the inserted entity in the payload. Possible + * values are return-no-content and return-content. Possible values include: 'return-no-content', + * 'return-content' + */ + public responsePreference?: ResponseFormat; + /** + * Additional parameters for the operation + */ + public queryOptions?: QueryOptions; +} diff --git a/src/table/batch/BatchTableMergeEntityOptionalParams.ts b/src/table/batch/BatchTableMergeEntityOptionalParams.ts new file mode 100644 index 000000000..270e9f94a --- /dev/null +++ b/src/table/batch/BatchTableMergeEntityOptionalParams.ts @@ -0,0 +1,46 @@ +import { + DataServiceVersion6, + QueryOptions, + ResponseFormat, + TableMergeEntityOptionalParams +} from "../generated/artifacts/models"; +import IOptionalParams from "./IOptionalParams"; + +/** + * Batch Table Merge Entity Optional Params + * + * @export + * @class BatchTableMergeEntityOptionalParams + * @implements {TableMergeEntityOptionalParams} + * @implements {IOptionalParams} + */ +export default class BatchTableMergeEntityOptionalParams + implements TableMergeEntityOptionalParams, IOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + public timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + public requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + public dataServiceVersion?: DataServiceVersion6; + /** + * The properties for the table entity. + */ + public tableEntityProperties?: { [propertyName: string]: any }; + /** + * Specifies whether the response should include the inserted entity in the payload. Possible + * values are return-no-content and return-content. Possible values include: 'return-no-content', + * 'return-content' + */ + public responsePreference?: ResponseFormat; + /** + * Additional parameters for the operation + */ + public queryOptions?: QueryOptions; +} diff --git a/src/table/batch/BatchTableQueryEntitiesOptionalParams.ts b/src/table/batch/BatchTableQueryEntitiesOptionalParams.ts new file mode 100644 index 000000000..54a526636 --- /dev/null +++ b/src/table/batch/BatchTableQueryEntitiesOptionalParams.ts @@ -0,0 +1,46 @@ +import { + DataServiceVersion3, + QueryOptions, + ResponseFormat, + TableQueryEntitiesOptionalParams +} from "../generated/artifacts/models"; +import IOptionalParams from "./IOptionalParams"; + +/** + * Batch Table Query Entities Optional Params + * + * @export + * @class BatchTableQueryEntitiesOptionalParams + * @implements {TableQueryEntitiesOptionalParams} + * @implements {IOptionalParams} + */ +export default class BatchTableQueryEntitiesOptionalParams + implements TableQueryEntitiesOptionalParams, IOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + public timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + public requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + public dataServiceVersion?: DataServiceVersion3; + /** + * The properties for the table entity. + */ + public tableEntityProperties?: { [propertyName: string]: any }; + /** + * Specifies whether the response should include the inserted entity in the payload. Possible + * values are return-no-content and return-content. Possible values include: 'return-no-content', + * 'return-content' + */ + public responsePreference?: ResponseFormat; + /** + * Additional parameters for the operation + */ + public queryOptions?: QueryOptions; +} diff --git a/src/table/batch/BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams.ts b/src/table/batch/BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams.ts new file mode 100644 index 000000000..5b0672371 --- /dev/null +++ b/src/table/batch/BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams.ts @@ -0,0 +1,48 @@ +import { + DataServiceVersion4, + QueryOptions, + ResponseFormat, + TableQueryEntitiesWithPartitionAndRowKeyOptionalParams +} from "../generated/artifacts/models"; +import IOptionalParams from "./IOptionalParams"; + +/** + * Batch Table Query Entities With Partition And RowKey Optional Params + * + * @export + * @class BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams + * @implements {TableQueryEntitiesWithPartitionAndRowKeyOptionalParams} + * @implements {IOptionalParams} + */ +export default class BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams + implements + TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, + IOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + public timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + public requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + public dataServiceVersion?: DataServiceVersion4; + /** + * The properties for the table entity. + */ + public tableEntityProperties?: { [propertyName: string]: any }; + /** + * Specifies whether the response should include the inserted entity in the payload. Possible + * values are return-no-content and return-content. Possible values include: 'return-no-content', + * 'return-content' + */ + public responsePreference?: ResponseFormat; + /** + * Additional parameters for the operation + */ + public queryOptions?: QueryOptions; +} diff --git a/src/table/batch/BatchTableUpdateEntityOptionalParams.ts b/src/table/batch/BatchTableUpdateEntityOptionalParams.ts new file mode 100644 index 000000000..01c5eb249 --- /dev/null +++ b/src/table/batch/BatchTableUpdateEntityOptionalParams.ts @@ -0,0 +1,46 @@ +import { + DataServiceVersion5, + QueryOptions, + ResponseFormat, + TableUpdateEntityOptionalParams +} from "../generated/artifacts/models"; +import IOptionalParams from "./IOptionalParams"; + +/** + * Batch Table Update Entity Optional Params + * + * @export + * @class BatchTableUpdateEntityOptionalParams + * @implements {TableUpdateEntityOptionalParams} + * @implements {IOptionalParams} + */ +export default class BatchTableUpdateEntityOptionalParams + implements TableUpdateEntityOptionalParams, IOptionalParams { + /** + * The timeout parameter is expressed in seconds. + */ + public timeout?: number; + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + */ + public requestId?: string; + /** + * Specifies the data service version. Possible values include: '3.0' + */ + public dataServiceVersion?: DataServiceVersion5; + /** + * The properties for the table entity. + */ + public tableEntityProperties?: { [propertyName: string]: any }; + /** + * Specifies whether the response should include the inserted entity in the payload. Possible + * values are return-no-content and return-content. Possible values include: 'return-no-content', + * 'return-content' + */ + public responsePreference?: ResponseFormat; + /** + * Additional parameters for the operation + */ + public queryOptions?: QueryOptions; +} diff --git a/src/table/batch/IOptionalParams.ts b/src/table/batch/IOptionalParams.ts new file mode 100644 index 000000000..64530aea8 --- /dev/null +++ b/src/table/batch/IOptionalParams.ts @@ -0,0 +1,58 @@ +import { + DataServiceVersion3, + DataServiceVersion4, + DataServiceVersion5, + DataServiceVersion6, + DataServiceVersion7, + DataServiceVersion9, + QueryOptions +} from "../generated/artifacts/models"; + +/** + * Interface to simplify the processing of batch requests which need to + * be sent through to the table handler. + * + * @export + * @interface IOptionalParams + */ +export default interface IOptionalParams { + /** + * Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the + * analytics logs when analytics logging is enabled. + * + * @type {(string | undefined)} + * @memberof IOptionalParams + */ + requestId?: string | undefined; + + /** + * Specifies the data service version. Possible values include: '3.0', although the service returns 1.0! + * + * @type {(DataServiceVersion4 | DataServiceVersion5 | undefined)} + * @memberof IOptionalParams + */ + dataServiceVersion?: + | DataServiceVersion3 + | DataServiceVersion4 + | DataServiceVersion5 + | DataServiceVersion6 + | DataServiceVersion7 + | DataServiceVersion9 + | undefined; + + /** + * The properties for the table entity. + * + * @type {{ [propertyName: string]: any }} + * @memberof IOptionalParams + */ + tableEntityProperties?: { [propertyName: string]: any }; + + /** + * Additional parameters for the operation + * + * @type {QueryOptions} + * @memberof IOptionalParams + */ + queryOptions?: QueryOptions; +} diff --git a/src/table/batch/TableBatchOperation.ts b/src/table/batch/TableBatchOperation.ts new file mode 100644 index 000000000..fafcfb102 --- /dev/null +++ b/src/table/batch/TableBatchOperation.ts @@ -0,0 +1,7 @@ +import BatchOperation, { BatchType } from "../../common/batch/BatchOperation"; + +export default class TableBatchOperation extends BatchOperation { + public constructor(_batchType: BatchType, headers: string) { + super(_batchType, headers); + } +} diff --git a/src/table/batch/TableBatchOrchestrator.ts b/src/table/batch/TableBatchOrchestrator.ts new file mode 100644 index 000000000..747f7011c --- /dev/null +++ b/src/table/batch/TableBatchOrchestrator.ts @@ -0,0 +1,536 @@ +import BatchRequest from "../../common/batch/BatchRequest"; +import BatchTableInsertEntityOptionalParams from "./BatchTableInsertEntityOptionalParams"; +import TableStorageContext from "../context/TableStorageContext"; +import Context from "../generated/Context"; +import TableHandler from "../handlers/TableHandler"; +import { TableBatchSerialization } from "./TableBatchSerialization"; +import TableBatchOperation from "./TableBatchOperation"; +import BatchTableDeleteEntityOptionalParams from "./BatchTableDeleteEntityOptionalParams"; +import BatchTableUpdateEntityOptionalParams from "./BatchTableUpdateEntityOptionalParams"; +import BatchTableMergeEntityOptionalParams from "./BatchTableMergeEntityOptionalParams"; +import BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams from "./BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams"; +import { + TableQueryEntitiesOptionalParams, + TableQueryEntitiesWithPartitionAndRowKeyOptionalParams +} from "../generated/artifacts/models"; +import BatchTableQueryEntitiesOptionalParams from "./BatchTableQueryEntitiesOptionalParams"; + +/** + * Currently there is a single distinct and concrete implementation of batch / + * entity group operations for the table api. + * The orchestrator manages the deserialization, submission and serialization of + * entity group transactions. + * ToDo: it might be possible to share code between this and the blob batch api, but this + * has not yet been validated. + * Will need refactoring when we address batch transactions for blob. + * + * @export + * @class TableBatchOrchestrator + */ +export default class TableBatchOrchestrator { + private batchOperations: TableBatchOperation[] = []; + private requests: BatchRequest[] = []; + private serialization = new TableBatchSerialization(); + private context: TableStorageContext; + private parentHandler: TableHandler; + + public constructor(context: TableStorageContext, handler: TableHandler) { + this.context = context; + this.parentHandler = handler; + } + + /** + * This is the central route / sequence of the batch orchestration. + * Takes batchRequest body, deserializes requests, submits to handlers, then returns serialized response + * + * @param {string} batchRequestBody + * @return {*} {Promise} + * @memberof TableBatchManager + */ + public async processBatchRequestAndSerializeResponse( + batchRequestBody: string + ): Promise { + this.batchOperations = this.serialization.deserializeBatchRequest( + batchRequestBody + ); + + await this.submitRequestsToHandlers(); + + return this.serializeResponses(); + } + + /** + * Submits requests to the appropriate handlers + * ToDo: Correct logic and handling of requests with Content ID + * + * @private + * @return {*} {Promise} + * @memberof TableBatchManager + */ + private async submitRequestsToHandlers(): Promise { + this.batchOperations.forEach((operation) => { + const request: BatchRequest = new BatchRequest(operation); + this.requests.push(request); + }); + + let contentID = 1; // contentID starts at 1 for batch + if (this.requests.length > 0) { + for (const singleReq of this.requests) { + try { + singleReq.response = await this.routeAndDispatchBatchRequest( + singleReq, + this.context, + contentID + ); + } catch (err) { + throw err; + } + contentID++; + } + } + } + + /** + * Serializes responses from the table handler + * see Link below for details of response format + * tslint:disable-next-line: max-line-length + * https://docs.microsoft.com/en-us/rest/api/storageservices/performing-entity-group-transactions#json-versions-2013-08-15-and-later-2 + * + * @private + * @return {*} {string} + * @memberof TableBatchManager + */ + private serializeResponses(): string { + let responseString: string = ""; + // based on research, a stringbuilder is only worth doing with 1000s of string ops + // this can be optimized later if we get reports of slow batch operations + const batchBoundary = this.serialization.batchBoundary.replace( + "batch", + "batchresponse" + ); + + let changesetBoundary = this.serialization.changesetBoundary.replace( + "changeset", + "changesetresponse" + ); + + responseString += batchBoundary + "\r\n"; + // (currently static header) ToDo: Validate if we need to correct headers via tests + responseString += + "Content-Type: multipart/mixed; boundary=" + changesetBoundary + "\r\n"; + changesetBoundary = "\r\n--" + changesetBoundary; + this.requests.forEach((request) => { + responseString += changesetBoundary; + responseString += request.response; + responseString += "\r\n\r\n"; + }); + responseString += changesetBoundary + "--\r\n"; + responseString += batchBoundary + "--\r\n"; + return responseString; + } + + /** + * Routes and dispatches single operations against the table handler and stores + * the serialized result. + * + * @private + * @param {BatchRequest} request + * @param {Context} context + * @param {number} contentID + * @return {*} {Promise} + * @memberof TableBatchManager + */ + private async routeAndDispatchBatchRequest( + request: BatchRequest, + context: Context, + contentID: number + ): Promise { + // the context that we have will not work with the calls and needs updating for + // batch operations, need a suitable deep clone, as each request needs to be treated seaprately + const batchContextClone = Object.create(context); + batchContextClone.tableName = request.getPath(); + batchContextClone.path = request.getPath(); + let response: any; + let __return: any; + // we only use 5 HTTP Verbs to determine the table operation type + try { + switch (request.getMethod()) { + case "POST": + // INSERT: we are inserting an entity + // POST https://myaccount.table.core.windows.net/mytable + ({ __return, response } = await this.handleBatchInsert( + request, + response, + batchContextClone, + contentID + )); + break; + case "PUT": + // UPDATE: we are updating an entity + // PUT http://127.0.0.1:10002/devstoreaccount1/mytable(PartitionKey='myPartitionKey', RowKey='myRowKey') + // INSERT OR REPLACE: + // PUT https://myaccount.table.core.windows.net/mytable(PartitionKey='myPartitionKey', RowKey='myRowKey') + ({ __return, response } = await this.handleBatchUpdate( + request, + response, + batchContextClone, + contentID + )); + break; + case "DELETE": + // DELETE: we are deleting an entity + // DELETE https://myaccount.table.core.windows.net/mytable(PartitionKey='myPartitionKey', RowKey='myRowKey') + ({ __return, response } = await this.handleBatchDelete( + request, + response, + batchContextClone, + contentID + )); + break; + case "GET": + // QUERY : we are querying / retrieving an entity + // GET https://myaccount.table.core.windows.net/mytable(PartitionKey='',RowKey='')?$select= + // GET https://myaccount.table.core.windows.net/mytable()?$filter=&$select= + ({ __return, response } = await this.handleBatchQuery( + request, + response, + batchContextClone, + contentID + )); + break; + case "CONNECT": + throw new Error("Connect Method unsupported in batch."); + break; + case "HEAD": + throw new Error("Head Method unsupported in batch."); + break; + case "OPTIONS": + throw new Error("Options Method unsupported in batch."); + break; + case "TRACE": + throw new Error("Trace Method unsupported in batch."); + break; + case "PATCH": + throw new Error("Patch Method unsupported in batch."); + break; + default: + // MERGE: this must be the merge, as the merge operation is not currently generated by autorest + // MERGE https://myaccount.table.core.windows.net/mytable(PartitionKey='myPartitionKey', RowKey='myRowKey') + // INSERT OR MERGE + // MERGE https://myaccount.table.core.windows.net/mytable(PartitionKey='myPartitionKey', RowKey='myRowKey') + ({ __return, response } = await this.handleBatchMerge( + request, + response, + batchContextClone, + contentID + )); + } + } catch (batchException) { + // this allows us to catch and debug any errors in the batch handling + throw batchException; + } + return __return; + } + + /** + * Helper function to extract values needed for handler calls + * + * @private + * @param {BatchRequest} request + * @return {*} {{ partitionKey: string; rowKey: string }} + * @memberof TableBatchManager + */ + private extractRowAndPartitionKeys( + request: BatchRequest + ): { partitionKey: string; rowKey: string } { + let partitionKey: string; + let rowKey: string; + + const url = request.getUrl(); + const partKeyMatch = url.match(/(PartitionKey=)(%27)?'?(\w+)/gi); + partitionKey = partKeyMatch ? partKeyMatch[0] : ""; + const rowKeyMatch = url.match(/(RowKey=)(%27)?'?(\w+)/gi); + rowKey = rowKeyMatch ? rowKeyMatch[0] : ""; + + if (partitionKey !== "" || rowKey !== "") { + // we need to filter out the delimeter (if URL encoded) + const urlencodedMatch = partitionKey.match(/%/); + let matchStringLength = 14; + if (urlencodedMatch) { + matchStringLength += 2; + } + partitionKey = partitionKey.substring(matchStringLength); + matchStringLength = 8; + if (urlencodedMatch) { + matchStringLength += 2; + } + rowKey = rowKey.substring(matchStringLength); + } else { + // row key not in URL, must be in body + const body = request.getBody(); + if (body !== "") { + const jsonBody = JSON.parse(body ? body : "{}"); + partitionKey = jsonBody.PartitionKey; + rowKey = jsonBody.RowKey; + } + } + return { partitionKey, rowKey }; + } + + /** + * Handles an insert operation inside a batch + * + * @private + * @param {BatchRequest} request + * @param {*} response + * @param {*} batchContextClone + * @param {number} contentID + * @return {*} {Promise<{ + * __return: string; + * response: any; + * }>} + * @memberof TableBatchManager + */ + private async handleBatchInsert( + request: BatchRequest, + response: any, + batchContextClone: any, + contentID: number + ): Promise<{ + __return: string; + response: any; + }> { + request.ingestOptionalParams(new BatchTableInsertEntityOptionalParams()); + const updatedContext = batchContextClone as TableStorageContext; + updatedContext.request = request; + response = await this.parentHandler.insertEntity( + request.getPath(), + request.params as BatchTableInsertEntityOptionalParams, + updatedContext + ); + return { + __return: this.serialization.serializeTableInsertEntityBatchResponse( + request, + response + ), + response + }; + } + + /** + * Handles a delete Operation inside a batch request + * + * @private + * @param {BatchRequest} request + * @param {*} response + * @param {*} batchContextClone + * @param {number} contentID + * @return {*} {Promise<{ + * __return: string; + * response: any; + * }>} + * @memberof TableBatchManager + */ + private async handleBatchDelete( + request: BatchRequest, + response: any, + batchContextClone: any, + contentID: number + ): Promise<{ + __return: string; + response: any; + }> { + request.ingestOptionalParams(new BatchTableDeleteEntityOptionalParams()); + const updatedContext = batchContextClone as TableStorageContext; + updatedContext.request = request; + let partitionKey: string; + let rowKey: string; + const ifmatch: string = request.getHeader("if-match") || "*"; + + ({ partitionKey, rowKey } = this.extractRowAndPartitionKeys(request)); + response = await this.parentHandler.deleteEntity( + request.getPath(), + partitionKey, + rowKey, + ifmatch, + request.params as BatchTableDeleteEntityOptionalParams, + updatedContext + ); + + return { + __return: this.serialization.serializeTableDeleteEntityBatchResponse( + request, + response + ), + response + }; + } + + /** + * Handles an update Operation inside a batch request + * + * @private + * @param {BatchRequest} request + * @param {*} response + * @param {*} batchContextClone + * @param {number} contentID + * @return {*} {Promise<{ + * __return: string; + * response: any; + * }>} + * @memberof TableBatchManager + */ + private async handleBatchUpdate( + request: BatchRequest, + response: any, + batchContextClone: any, + contentID: number + ): Promise<{ + __return: string; + response: any; + }> { + request.ingestOptionalParams(new BatchTableUpdateEntityOptionalParams()); + const updatedContext = batchContextClone as TableStorageContext; + updatedContext.request = request; + let partitionKey: string; + let rowKey: string; + ({ partitionKey, rowKey } = this.extractRowAndPartitionKeys(request)); + + response = await this.parentHandler.updateEntity( + request.getPath(), + partitionKey, + rowKey, + request.params as BatchTableUpdateEntityOptionalParams, + updatedContext + ); + + return { + __return: this.serialization.serializeTableUpdateEntityBatchResponse( + request, + response + ), + response + }; + } + + /** + * Handles a query operation inside a batch request, + * should only ever be one operation if there is a query + * + * @private + * @param {BatchRequest} request + * @param {*} response + * @param {*} batchContextClone + * @param {number} contentID + * @return {*} {Promise<{ + * __return: string; + * response: any; + * }>} + * @memberof TableBatchManager + */ + private async handleBatchQuery( + request: BatchRequest, + response: any, + batchContextClone: any, + contentID: number + ): Promise<{ + __return: string; + response: any; + }> { + let partitionKey: string; + let rowKey: string; + ({ partitionKey, rowKey } = this.extractRowAndPartitionKeys(request)); + + const updatedContext = batchContextClone as TableStorageContext; + + if (null !== partitionKey && null != rowKey) { + // ToDo: this is hideous... but we need the params on the request object, + // as they percolate through and are needed for the final serialization + // currently, because of the way we deconstruct / deserialize, we only + // have the right model at a very late stage in processing + // this might resolve when we simplify Query logic + // based on only accepting Query iwth partition and row key + request.ingestOptionalParams( + new BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams() + ); + + updatedContext.request = request; + response = await this.parentHandler.queryEntitiesWithPartitionAndRowKey( + request.getPath(), + partitionKey, + rowKey, + request.params as TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, + updatedContext + ); + return { + __return: await this.serialization.serializeTableQueryEntityWithPartitionAndRowKeyBatchResponse( + request, + response + ), + response + }; + } else { + request.ingestOptionalParams(new BatchTableQueryEntitiesOptionalParams()); + updatedContext.request = request; + response = await this.parentHandler.queryEntities( + request.getPath(), + request.params as TableQueryEntitiesOptionalParams, + updatedContext + ); + return { + __return: await this.serialization.serializeTableQueryEntityBatchResponse( + request, + response + ), + response + }; + } + } + + /** + * Handles a merge operation inside a batch request + * + * @private + * @param {BatchRequest} request + * @param {*} response + * @param {*} batchContextClone + * @param {number} contentID + * @return {*} {Promise<{ + * __return: string; + * response: any; + * }>} + * @memberof TableBatchManager + */ + private async handleBatchMerge( + request: BatchRequest, + response: any, + batchContextClone: any, + contentID: number + ): Promise<{ + __return: string; + response: any; + }> { + request.ingestOptionalParams(new BatchTableMergeEntityOptionalParams()); + const updatedContext = batchContextClone as TableStorageContext; + updatedContext.request = request; + let partitionKey: string; + let rowKey: string; + ({ partitionKey, rowKey } = this.extractRowAndPartitionKeys(request)); + + response = await this.parentHandler.mergeEntity( + request.getPath(), + partitionKey, + rowKey, + request.params as BatchTableMergeEntityOptionalParams, + updatedContext + ); + + return { + __return: this.serialization.serializeTablMergeEntityBatchResponse( + request, + response + ), + response + }; + } +} diff --git a/src/table/batch/TableBatchSerialization.ts b/src/table/batch/TableBatchSerialization.ts new file mode 100644 index 000000000..ca78c3e2e --- /dev/null +++ b/src/table/batch/TableBatchSerialization.ts @@ -0,0 +1,575 @@ +import { StorageError } from "../../blob/generated/artifacts/mappers"; +// import BatchOperation from "../../common/BatchOperation"; +// import { BatchOperationType } from "../../common/BatchOperation"; +import { BatchType } from "../../common/batch/BatchOperation"; +import BatchRequest from "../../common/batch/BatchRequest"; +// import BatchSubResponse from "../../common/BatchSubResponse"; + +import { HttpMethod } from "../../table/generated/IRequest"; +import { BatchSerialization } from "../../common/batch/BatchSerialization"; +import TableBatchOperation from "../batch/TableBatchOperation"; +import * as Models from "../generated/artifacts/models"; +import TableBatchUtils from "./TableBatchUtils"; + +/** + * The semantics for entity group transactions are defined by the OData Protocol Specification. + * https://www.odata.org/ + * http://docs.oasis-open.org/odata/odata-json-format/v4.01/odata-json-format-v4.01.html#_Toc38457781 + * + * for now we are first getting the concrete implementation correct for table batch + * we then need to figure out how to do this for blob, and what can be shared. + * We set several headers in the responses to the same values that we see returned + * from the Azure Storage Service. + * + * @export + * @class TableBatchSerialization + * @extends {BatchSerialization} + */ +export class TableBatchSerialization extends BatchSerialization { + /** + * Deserializes a batch request + * + * @param {string} batchRequestsString + * @return {*} {TableBatchOperation[]} + * @memberof TableBatchSerialization + */ + public deserializeBatchRequest( + batchRequestsString: string + ): TableBatchOperation[] { + this.extractBatchBoundary(batchRequestsString); + this.extractChangeSetBoundary(batchRequestsString); + this.extractLineEndings(batchRequestsString); + // we can't rely on case of strings we use in delimiters + // ToDo: might be easier and more efficient to use i option on the regex here... + const contentTypeHeaderString = this.extractRequestHeaderString( + batchRequestsString, + "(\\n)+(([c,C])+(ontent-)+([t,T])+(ype)+)+(?=:)+" + ); + const contentTransferEncodingString = this.extractRequestHeaderString( + batchRequestsString, + "(\\n)+(([c,C])+(ontent-)+([t,T])+(ransfer-)+([e,E])+(ncoding))+(?=:)+" + ); + + // the line endings might be \r\n or \n + const HTTP_LINE_ENDING = this.lineEnding; + const subRequestPrefix = `--${this.changesetBoundary}${HTTP_LINE_ENDING}${contentTypeHeaderString}: application/http${HTTP_LINE_ENDING}${contentTransferEncodingString}: binary`; + const splitBody = batchRequestsString.split(subRequestPrefix); + + // dropping first element as boundary if we have a batch with multiple requests + let subRequests: string[]; + if (splitBody.length > 1) { + subRequests = splitBody.slice(1, splitBody.length); + } else { + subRequests = splitBody; + } + + // This goes through each operation in the the request and maps the content + // of the request by deserializing it into a BatchOperation Type + const batchOperations: TableBatchOperation[] = subRequests.map( + (subRequest) => { + let requestType: RegExpMatchArray | null = []; + requestType = subRequest.match("(GET|POST|PUT|MERGE|INSERT|DELETE)"); + if (requestType === null || requestType.length < 2) { + throw new Error( + `Couldn't extract verb from sub-Request:\n ${subRequest}` + ); + } + + const fullRequestURI = subRequest.match(/((http+s?)(\S)+)/); + if (fullRequestURI === null || fullRequestURI.length < 3) { + throw new Error( + `Couldn't extract full request URL from sub-Request:\n ${subRequest}` + ); + } + + // extract the request path + const pathString = fullRequestURI[1]; + const path = pathString.match(/\S+devstoreaccount1\/(\w+)/); + if (path === null || path.length < 2) { + throw new Error( + `Couldn't extract path from URL in sub-Request:\n ${subRequest}` + ); + } + + const jsonOperationBody = subRequest.match(/{+.+}+/); + + // ToDo: not sure if this logic is valid, it might be better + // to just have an empty body and then error out when determining routing of request in Handler + if ( + subRequests.length > 1 && + null !== requestType && + requestType[0] !== "DELETE" && + (jsonOperationBody === null || jsonOperationBody.length < 1) + ) { + throw new Error( + `Couldn't extract path from sub-Request:\n ${subRequest}` + ); + } + + let headers: string; + let jsonBody: string; + let subStringStart: number; + let subStringEnd: number; + // currently getting an invalid header in the first position + // during table entity test for insert & merge + subStringStart = subRequest.indexOf(fullRequestURI[1]); + subStringStart += fullRequestURI[1].length + 1; // for the space + + if (jsonOperationBody != null) { + // we need the jsonBody and request path extracted to be able to extract headers. + subStringEnd = subRequest.indexOf(jsonOperationBody[0]); + jsonBody = jsonOperationBody[0]; + } else { + subStringEnd = subRequest.length - this.changesetBoundary.length - 2; + jsonBody = ""; + } + + headers = subRequest.substring(subStringStart, subStringEnd); + + const operation = new TableBatchOperation(BatchType.table, headers); + if (null !== requestType) { + operation.httpMethod = requestType[0] as HttpMethod; + } + operation.path = path[1]; + operation.uri = fullRequestURI[0]; + operation.jsonRequestBody = jsonBody; + return operation; + } + ); + + return batchOperations; + } + + /** + * Serializes an Insert entity response + * + * @param {BatchRequest} request + * @param {Models.TableInsertEntityResponse} response + * @return {*} {string} + * @memberof TableBatchSerialization + */ + public serializeTableInsertEntityBatchResponse( + request: BatchRequest, + response: Models.TableInsertEntityResponse + ): string { + let serializedResponses: string = ""; + serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); + serializedResponses = this.serializeHttpStatusCode( + serializedResponses, + response + ); + // ToDo: Correct the handling of Content-ID + if (request.contentID !== undefined) { + serializedResponses += + "Content-ID: " + request.contentID.toString() + "\r\n"; + } + + serializedResponses = this.AddNoSniffNoCache(serializedResponses); + + serializedResponses = this.serializePreferenceApplied( + request, + serializedResponses + ); + + serializedResponses = this.serializeDataServiceVersion( + request, + serializedResponses + ); + + serializedResponses += + "Location: " + this.SerializeEntityPath(serializedResponses, request); + serializedResponses += + "DataServiceId: " + + this.SerializeEntityPath(serializedResponses, request); + + if (null !== response.eTag && undefined !== response.eTag) { + // prettier-ignore + serializedResponses += "ETag: " + response.eTag.replace(":","%3A"); + } + return serializedResponses; + } + + /** + * creates the serialized entitygrouptransaction / batch response body + * which we return to the users batch request + * + * @param {BatchRequest} request + * @param {Models.TableDeleteEntityResponse} response + * @return {*} {string} + * @memberof TableBatchSerialization + */ + public serializeTableDeleteEntityBatchResponse( + request: BatchRequest, + response: Models.TableDeleteEntityResponse + ): string { + // ToDo: keeping my life easy to start and defaulting to "return no content" + let serializedResponses: string = ""; + // create the initial boundary + serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); + serializedResponses = this.serializeHttpStatusCode( + serializedResponses, + response + ); + + serializedResponses = this.AddNoSniffNoCache(serializedResponses); + serializedResponses = this.serializeDataServiceVersion( + request, + serializedResponses + ); + + return serializedResponses; + } + + /** + * Serializes the Update Entity Batch Response + * + * @param {BatchRequest} request + * @param {Models.TableUpdateEntityResponse} response + * @return {*} {string} + * @memberof TableBatchSerialization + */ + public serializeTableUpdateEntityBatchResponse( + request: BatchRequest, + response: Models.TableUpdateEntityResponse + ): string { + let serializedResponses: string = ""; + // create the initial boundary + serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); + serializedResponses = this.serializeHttpStatusCode( + serializedResponses, + response + ); + // ToDo_: Correct the handling of content-ID + if (request.contentID) { + serializedResponses += + "Content-ID: " + request.contentID.toString() + "\r\n"; + } + + serializedResponses = this.AddNoSniffNoCache(serializedResponses); + + serializedResponses = this.serializePreferenceApplied( + request, + serializedResponses + ); + + serializedResponses = this.serializeDataServiceVersion( + request, + serializedResponses + ); + + if (null !== response.eTag && undefined !== response.eTag) { + serializedResponses += "ETag: " + response.eTag.replace(":", "%3A"); + } + return serializedResponses; + } + + /** + * Serializes the preference applied header + * + * @private + * @param {BatchRequest} request + * @param {string} serializedResponses + * @return {*} + * @memberof TableBatchSerialization + */ + private serializePreferenceApplied( + request: BatchRequest, + serializedResponses: string + ) { + if (request.getHeader("Preference-Applied")) { + serializedResponses += + "Preference-Applied: " + + request.getHeader("Preference-Applied") + + "\r\n"; + } + return serializedResponses; + } + + /** + * Serializes the Merge Entity Response + * + * @param {BatchRequest} request + * @param {Models.TableMergeEntityResponse} response + * @return {*} {string} + * @memberof TableBatchSerialization + */ + public serializeTablMergeEntityBatchResponse( + request: BatchRequest, + response: Models.TableMergeEntityResponse + ): string { + let serializedResponses: string = ""; + serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); + serializedResponses = this.serializeHttpStatusCode( + serializedResponses, + response + ); + serializedResponses = this.AddNoSniffNoCache(serializedResponses); + // ToDo_: Correct the handling of content-ID + if (request.contentID) { + serializedResponses += + "Content-ID: " + request.contentID.toString() + "\r\n"; + } + // ToDo: not sure about other headers like cache control etc right now + // Service defaults to v1.0 + serializedResponses = this.serializeDataServiceVersion( + request, + serializedResponses + ); + + if (null !== response.eTag && undefined !== response.eTag) { + serializedResponses += "ETag: " + response.eTag.replace(":", "%3A"); + } + return serializedResponses; + } + + /** + * Serializes the Query Entity Response when using Partition and Row Key + * + * @param {BatchRequest} request + * @param {Models.TableQueryEntitiesWithPartitionAndRowKeyResponse} response + * @return {*} {Promise} + * @memberof TableBatchSerialization + */ + public async serializeTableQueryEntityWithPartitionAndRowKeyBatchResponse( + request: BatchRequest, + response: Models.TableQueryEntitiesWithPartitionAndRowKeyResponse + ): Promise { + let serializedResponses: string = ""; + // create the initial boundary + serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); + serializedResponses = this.serializeHttpStatusCode( + serializedResponses, + response + ); + + serializedResponses = this.serializeDataServiceVersion( + request, + serializedResponses + ); + + serializedResponses += "Content-Type: "; + serializedResponses += request.params.queryOptions?.format; + serializedResponses += ";streaming=true;charset=utf-8\r\n"; // getting this from service, so adding here as well + + serializedResponses = this.AddNoSniffNoCache(serializedResponses); + + if (response.eTag) { + serializedResponses += "ETag: " + response.eTag.replace(":", "%3A"); + } + serializedResponses += "\r\n"; + + // now we need to return the JSON body + // ToDo: I don't like the stream to string to stream conversion here... + // just not sure there is any way around it + if (response.body != null) { + try { + serializedResponses += await TableBatchUtils.StreamToString( + response.body + ); + } catch { + // do nothing + throw new Error("failed to deserialize body"); + } + } + serializedResponses += "\r\n"; + return serializedResponses; + } + + /** + * Serializes query entity response + * + * @param {BatchRequest} request + * @param {Models.TableQueryEntitiesResponse} response + * @return {*} {Promise} + * @memberof TableBatchSerialization + */ + public async serializeTableQueryEntityBatchResponse( + request: BatchRequest, + response: Models.TableQueryEntitiesResponse + ): Promise { + let serializedResponses: string = ""; + serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); + serializedResponses = this.serializeHttpStatusCode( + serializedResponses, + response + ); + + serializedResponses = this.serializeDataServiceVersion( + request, + serializedResponses + ); + + serializedResponses += "Content-Type: "; + serializedResponses += request.params.queryOptions?.format; + serializedResponses += ";streaming=true;charset=utf-8\r\n"; // getting this from service, so adding as well + + // Azure Table service defaults to this in the response + // X-Content-Type-Options: nosniff\r\n + serializedResponses = this.AddNoSniffNoCache(serializedResponses); + + serializedResponses += "\r\n"; + + // now we need to return the JSON body + // ToDo: I don't like the stream to string to stream conversion here... + // just not sure there is any way around it + if (response.body != null) { + try { + serializedResponses += await TableBatchUtils.StreamToString( + response.body + ); + } catch { + // Throw a more helpful error + throw new Error("failed to deserialize body"); + } + } + serializedResponses += "\r\n"; + return serializedResponses; + } + + /** + * Serializes content type and encoding + * + * @private + * @param {string} serializedResponses + * @return {*} + * @memberof TableBatchSerialization + */ + private SetContentTypeAndEncoding(serializedResponses: string) { + serializedResponses += "\r\nContent-Type: application/http\r\n"; + serializedResponses += "Content-Transfer-Encoding: binary\r\n"; + serializedResponses += "\r\n"; + return serializedResponses; + } + + /** + * Serializes Content Type Options and Cache Control + * THese seem to be service defaults + * + * @private + * @param {string} serializedResponses + * @return {*} + * @memberof TableBatchSerialization + */ + private AddNoSniffNoCache(serializedResponses: string) { + serializedResponses += "X-Content-Type-Options: nosniff\r\n"; + serializedResponses += "Cache-Control: no-cache\r\n"; + return serializedResponses; + } + + /** + * Serializes the HTTP response + * ToDo: Need to check where we have implemented this elsewhere and see if we can reuse + * + * @private + * @param {number} statusCode + * @return {*} {string} + * @memberof TableBatchSerialization + */ + private GetStatusMessageString(statusCode: number): string { + switch (statusCode) { + case 200: + return "OK"; + case 201: + return "Created"; + case 204: + return "No Content"; + case 404: + return "Not Found"; + default: + return "STATUS_CODE_NOT_IMPLEMENTED"; + } + } + + /** + * extract a header request string + * + * @private + * @param {string} batchRequestsString + * @param {string} regExPattern + * @return {*} + * @memberof TableBatchSerialization + */ + private extractRequestHeaderString( + batchRequestsString: string, + regExPattern: string + ) { + const headerStringMatches = batchRequestsString.match(regExPattern); + if (headerStringMatches == null) { + throw StorageError; + } + return headerStringMatches[2]; + } + + /** + * Serialize HTTP Status Code + * + * @private + * @param {string} serializedResponses + * @param {*} response + * @return {*} + * @memberof TableBatchSerialization + */ + private serializeHttpStatusCode(serializedResponses: string, response: any) { + serializedResponses += + "HTTP/1.1 " + + response.statusCode.toString() + + " " + + this.GetStatusMessageString(response.statusCode) + + "\r\n"; + return serializedResponses; + } + + /** + * Serializes the Location and DataServiceId for the response + * These 2 headers should point to the result of the successful insert + * https://docs.microsoft.com/de-de/dotnet/api/microsoft.azure.batch.addtaskresult.location?view=azure-dotnet#Microsoft_Azure_Batch_AddTaskResult_Location + * https://docs.microsoft.com/de-de/dotnet/api/microsoft.azure.batch.protocol.models.taskgetheaders.dataserviceid?view=azure-dotnet + * i.e. Location: http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='7219c1f2e2674f249bf9589d31ab3c6e',RowKey='sentinel') + * + * @private + * @param {string} serializedResponses + * @param {BatchRequest} request + * @return {string} + * @memberof TableBatchSerialization + */ + private SerializeEntityPath( + serializedResponses: string, + request: BatchRequest + ): string { + let parenthesesPosition: number = request.getUrl().indexOf("("); + parenthesesPosition--; + if (parenthesesPosition < 0) { + parenthesesPosition = request.getUrl().length; + } + const trimmedUrl: string = request + .getUrl() + .substring(0, parenthesesPosition); + let entityPath = trimmedUrl + "(PartitionKey=%27"; + entityPath += request.params.tableEntityProperties!.PartitionKey; + entityPath += "%27,"; + entityPath += "RowKey=%27"; + entityPath += request.params.tableEntityProperties!.RowKey; + entityPath += "%27)\r\n"; + return entityPath; + } + + /** + * serializes data service version + * + * @private + * @param {BatchRequest} request + * @param {string} serializedResponses + * @return {*} + * @memberof TableBatchSerialization + */ + private serializeDataServiceVersion( + request: BatchRequest, + serializedResponses: string + ) { + if (undefined !== request.params && request.params.dataServiceVersion) { + serializedResponses += + "DataServiceVersion: " + request.params.dataServiceVersion + ";\r\n"; + } + return serializedResponses; + } +} diff --git a/src/table/batch/TableBatchUtils.ts b/src/table/batch/TableBatchUtils.ts new file mode 100644 index 000000000..3a26acb0e --- /dev/null +++ b/src/table/batch/TableBatchUtils.ts @@ -0,0 +1,23 @@ +export default class TableBatchUtils { + /** + * Helper to convert a ReadableStream to string. + * + * @static + * @param {(NodeJS.ReadableStream | undefined)} stream + * @return {*} {Promise} + * @memberof TableBatchUtils + */ + public static async StreamToString( + stream: NodeJS.ReadableStream | undefined + ): Promise { + if (stream === undefined) { + throw new Error("undefined stream passed to function!"); + } + const chunks: any[] = []; + return new Promise((resolve, reject) => { + stream.on("data", (chunk) => chunks.push(chunk)); + stream.on("error", reject); + stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8"))); + }); + } +} diff --git a/src/table/generated/artifacts/models.ts b/src/table/generated/artifacts/models.ts index 3441ef3c6..8db9da6e9 100644 --- a/src/table/generated/artifacts/models.ts +++ b/src/table/generated/artifacts/models.ts @@ -1173,9 +1173,9 @@ export interface ServiceGetStatisticsHeaders { * @enum {string} */ export enum GeoReplicationStatusType { - Live = 'live', - Bootstrap = 'bootstrap', - Unavailable = 'unavailable', + Live = "live", + Bootstrap = "bootstrap", + Unavailable = "unavailable" } /** @@ -1186,9 +1186,9 @@ export enum GeoReplicationStatusType { * @enum {string} */ export enum OdataMetadataFormat { - Applicationjsonodatanometadata = 'application/json;odata=nometadata', - Applicationjsonodataminimalmetadata = 'application/json;odata=minimalmetadata', - Applicationjsonodatafullmetadata = 'application/json;odata=fullmetadata', + Applicationjsonodatanometadata = "application/json;odata=nometadata", + Applicationjsonodataminimalmetadata = "application/json;odata=minimalmetadata", + Applicationjsonodatafullmetadata = "application/json;odata=fullmetadata" } /** @@ -1198,8 +1198,8 @@ export enum OdataMetadataFormat { * @enum {string} */ export enum ResponseFormat { - ReturnNoContent = 'return-no-content', - ReturnContent = 'return-content', + ReturnNoContent = "return-no-content", + ReturnContent = "return-content" } /** @@ -1209,7 +1209,7 @@ export enum ResponseFormat { * @enum {string} */ export enum Version { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1219,7 +1219,7 @@ export enum Version { * @enum {string} */ export enum DataServiceVersion { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1229,7 +1229,7 @@ export enum DataServiceVersion { * @enum {string} */ export enum DataServiceVersion1 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1239,17 +1239,20 @@ export enum DataServiceVersion1 { * @enum {string} */ export enum DataServiceVersion2 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** * Defines values for DataServiceVersion3. * Possible values include: '3.0' + * Changing all table batch related logic to point to this version + * becuase the other versions seem redundant and are complicating the code + * unnecessarily * @readonly * @enum {string} */ export enum DataServiceVersion3 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1259,7 +1262,7 @@ export enum DataServiceVersion3 { * @enum {string} */ export enum DataServiceVersion4 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1269,7 +1272,7 @@ export enum DataServiceVersion4 { * @enum {string} */ export enum DataServiceVersion5 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1279,7 +1282,7 @@ export enum DataServiceVersion5 { * @enum {string} */ export enum DataServiceVersion6 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1289,7 +1292,7 @@ export enum DataServiceVersion6 { * @enum {string} */ export enum DataServiceVersion7 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1299,7 +1302,7 @@ export enum DataServiceVersion7 { * @enum {string} */ export enum DataServiceVersion8 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1309,7 +1312,7 @@ export enum DataServiceVersion8 { * @enum {string} */ export enum DataServiceVersion9 { - ThreeFullStopZero = '3.0', + ThreeFullStopZero = "3.0" } /** @@ -1319,7 +1322,7 @@ export enum DataServiceVersion9 { * @enum {string} */ export enum Version1 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1329,7 +1332,7 @@ export enum Version1 { * @enum {string} */ export enum Version2 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1339,7 +1342,7 @@ export enum Version2 { * @enum {string} */ export enum Version3 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1349,7 +1352,7 @@ export enum Version3 { * @enum {string} */ export enum Version4 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1359,7 +1362,7 @@ export enum Version4 { * @enum {string} */ export enum Version5 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1369,7 +1372,7 @@ export enum Version5 { * @enum {string} */ export enum Version6 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1379,7 +1382,7 @@ export enum Version6 { * @enum {string} */ export enum Version7 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1389,7 +1392,7 @@ export enum Version7 { * @enum {string} */ export enum Version8 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1399,7 +1402,7 @@ export enum Version8 { * @enum {string} */ export enum Version9 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1409,7 +1412,7 @@ export enum Version9 { * @enum {string} */ export enum Version10 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1419,7 +1422,7 @@ export enum Version10 { * @enum {string} */ export enum Version11 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1429,7 +1432,7 @@ export enum Version11 { * @enum {string} */ export enum Version12 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1439,7 +1442,7 @@ export enum Version12 { * @enum {string} */ export enum Version13 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1449,7 +1452,7 @@ export enum Version13 { * @enum {string} */ export enum Version14 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1459,7 +1462,7 @@ export enum Version14 { * @enum {string} */ export enum Version15 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** @@ -1469,28 +1472,30 @@ export enum Version15 { * @enum {string} */ export enum Version16 { - TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = '2019-02-02', + TwoZeroOneNineHyphenMinusZeroTwoHyphenMinusZeroTwo = "2019-02-02" } /** * Contains response data for the query operation. */ -export type TableQueryResponse2 = TableQueryResponse & TableQueryHeaders & { - /** - * The response status code. - */ - statusCode: 200; -}; +export type TableQueryResponse2 = TableQueryResponse & + TableQueryHeaders & { + /** + * The response status code. + */ + statusCode: 200; + }; /** * Contains response data for the create operation. */ -export type TableCreateResponse = TableResponse & TableCreateHeaders & { - /** - * The response status code. - */ - statusCode: 201 | 204; -}; +export type TableCreateResponse = TableResponse & + TableCreateHeaders & { + /** + * The response status code. + */ + statusCode: 201 | 204; + }; /** * Contains response data for the batch operation. @@ -1605,12 +1610,13 @@ export type TableInsertEntityResponse = TableInsertEntityHeaders & { /** * Contains response data for the getAccessPolicy operation. */ -export type TableGetAccessPolicyResponse = Array & TableGetAccessPolicyHeaders & { - /** - * The response status code. - */ - statusCode: 200; -}; +export type TableGetAccessPolicyResponse = Array & + TableGetAccessPolicyHeaders & { + /** + * The response status code. + */ + statusCode: 200; + }; /** * Contains response data for the setAccessPolicy operation. @@ -1635,19 +1641,21 @@ export type ServiceSetPropertiesResponse = ServiceSetPropertiesHeaders & { /** * Contains response data for the getProperties operation. */ -export type ServiceGetPropertiesResponse = TableServiceProperties & ServiceGetPropertiesHeaders & { - /** - * The response status code. - */ - statusCode: 200; -}; +export type ServiceGetPropertiesResponse = TableServiceProperties & + ServiceGetPropertiesHeaders & { + /** + * The response status code. + */ + statusCode: 200; + }; /** * Contains response data for the getStatistics operation. */ -export type ServiceGetStatisticsResponse = TableServiceStats & ServiceGetStatisticsHeaders & { - /** - * The response status code. - */ - statusCode: 200; -}; +export type ServiceGetStatisticsResponse = TableServiceStats & + ServiceGetStatisticsHeaders & { + /** + * The response status code. + */ + statusCode: 200; + }; diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index 09c7b09d4..e2306abd8 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -1,5 +1,6 @@ import BufferStream from "../../common/utils/BufferStream"; import { newTableEntityEtag } from "../../common/utils/utils"; +import TableBatchOrchestrator from "../batch/TableBatchOrchestrator"; import TableStorageContext from "../context/TableStorageContext"; import { NormalizedEntity } from "../entity/NormalizedEntity"; import NotImplementedError from "../errors/NotImplementedError"; @@ -27,6 +28,8 @@ import { updateTableOptionalOdataAnnotationsForResponse } from "../utils/utils"; import BaseHandler from "./BaseHandler"; +import TableBatchUtils from "../batch/TableBatchUtils"; +import toReadableStream from "to-readable-stream"; interface IPartialResponsePreferProperties { statusCode: 200 | 201 | 204; @@ -168,8 +171,8 @@ export default class TableHandler extends BaseHandler implements ITableHandler { if ( !options.tableEntityProperties || !options.tableEntityProperties.PartitionKey || - (!options.tableEntityProperties.RowKey && - options.tableEntityProperties.RowKey !== "") + // rowKey may be empty string + options.tableEntityProperties.RowKey === null ) { throw StorageErrorFactory.getPropertiesNeedValue(context); } @@ -246,18 +249,20 @@ export default class TableHandler extends BaseHandler implements ITableHandler { } // TODO: Create data structures to hold entity properties and support serialize, merge, deserialize, filter + // Note: Batch is using the partition key and row key args, handler receives these values from middleware via + // context public async updateEntity( _table: string, - _partitionKey: string, - _rowKey: string, + partitionKey: string, + rowKey: string, options: Models.TableUpdateEntityOptionalParams, context: Context ): Promise { const tableContext = new TableStorageContext(context); const account = this.getAndCheckAccountName(tableContext); const table = this.getAndCheckTableName(tableContext); - const partitionKey = this.getAndCheckPartitionKey(tableContext); - const rowKey = this.getAndCheckRowKey(tableContext); + partitionKey = partitionKey || this.getAndCheckPartitionKey(tableContext); + rowKey = rowKey || this.getAndCheckRowKey(tableContext); const ifMatch = options.ifMatch; if (!options.tableEntityProperties) { @@ -326,16 +331,16 @@ export default class TableHandler extends BaseHandler implements ITableHandler { public async mergeEntity( _table: string, - _partitionKey: string, - _rowKey: string, + partitionKey: string, + rowKey: string, options: Models.TableMergeEntityOptionalParams, context: Context ): Promise { const tableContext = new TableStorageContext(context); const account = this.getAndCheckAccountName(tableContext); const table = this.getAndCheckTableName(tableContext); - const partitionKey = this.getAndCheckPartitionKey(tableContext); - const rowKey = this.getAndCheckRowKey(tableContext); + partitionKey = partitionKey || this.getAndCheckPartitionKey(tableContext); + rowKey = rowKey || this.getAndCheckRowKey(tableContext); if (!options.tableEntityProperties) { throw StorageErrorFactory.getPropertiesNeedValue(context); @@ -394,16 +399,16 @@ export default class TableHandler extends BaseHandler implements ITableHandler { public async deleteEntity( _table: string, - _partitionKey: string, - _rowKey: string, + partitionKey: string, + rowKey: string, ifMatch: string, options: Models.TableDeleteEntityOptionalParams, context: Context ): Promise { const tableContext = new TableStorageContext(context); const accountName = tableContext.account; - const partitionKey = tableContext.partitionKey!; // Get partitionKey from context - const rowKey = tableContext.rowKey!; // Get rowKey from context + partitionKey = partitionKey || tableContext.partitionKey!; // Get partitionKey from context + rowKey = rowKey || tableContext.rowKey!; // Get rowKey from context if (!partitionKey || !rowKey) { throw StorageErrorFactory.getPropertiesNeedValue(context); @@ -534,16 +539,16 @@ export default class TableHandler extends BaseHandler implements ITableHandler { public async queryEntitiesWithPartitionAndRowKey( _table: string, - _partitionKey: string, - _rowKey: string, + partitionKey: string, + rowKey: string, options: Models.TableQueryEntitiesWithPartitionAndRowKeyOptionalParams, context: Context ): Promise { const tableContext = new TableStorageContext(context); const account = this.getAndCheckAccountName(tableContext); - const table = this.getAndCheckTableName(tableContext); - const partitionKey = this.getAndCheckPartitionKey(tableContext); - const rowKey = this.getAndCheckRowKey(tableContext); + const table = _table ? _table : this.getAndCheckTableName(tableContext); + partitionKey = partitionKey || this.getAndCheckPartitionKey(tableContext); + rowKey = rowKey || this.getAndCheckRowKey(tableContext); const accept = this.getAndCheckPayloadFormat(tableContext); const entity = await this.metadataStore.queryTableEntitiesWithPartitionAndRowKey( @@ -651,6 +656,17 @@ export default class TableHandler extends BaseHandler implements ITableHandler { throw new NotImplementedError(context); } + /** + * Processes an entity group transaction request / batch request + * + * @param {NodeJS.ReadableStream} body + * @param {string} multipartContentType + * @param {number} contentLength + * @param {Models.TableBatchOptionalParams} options + * @param {Context} context + * @return {*} {Promise} + * @memberof TableHandler + */ public async batch( body: NodeJS.ReadableStream, multipartContentType: string, @@ -658,14 +674,26 @@ export default class TableHandler extends BaseHandler implements ITableHandler { options: Models.TableBatchOptionalParams, context: Context ): Promise { - const tableContext = new TableStorageContext(context); - // TODO: Implement batch operation logic here + const tableCtx = new TableStorageContext(context); + const contentTypeResponse = tableCtx.request + ?.getHeader("content-type") + ?.replace("batch", "batchresponse"); + const tableBatchManager = new TableBatchOrchestrator(tableCtx, this); + + const response = await tableBatchManager.processBatchRequestAndSerializeResponse( + await TableBatchUtils.StreamToString(body) + ); + + // need to convert response to NodeJS.ReadableStream + body = toReadableStream(response); + return { - requestId: tableContext.contextID, + contentType: contentTypeResponse, + requestId: tableCtx.contextID, version: TABLE_API_VERSION, date: context.startTime, statusCode: 202, - body // Use incoming request body as Batch operation response body as demo + body }; } diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index 28ed5dc3d..0f59560c9 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -551,7 +551,16 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { } // Test if etag value is valid - if (ifMatch === undefined || ifMatch === "*" || doc.eTag === ifMatch) { + const encodedEtag = doc.eTag.replace(":", "%3A").replace(":", "%3A"); + let encodedIfMatch: string | undefined; + if (ifMatch !== undefined) { + encodedIfMatch = ifMatch!.replace(":", "%3A").replace(":", "%3A"); + } + if ( + encodedIfMatch === undefined || + encodedIfMatch === "*" || + (encodedIfMatch !== undefined && encodedEtag === encodedIfMatch) + ) { tableEntityCollection.remove(doc); entity.properties.Timestamp = getTimestampString(entity.lastModifiedTime); @@ -596,7 +605,18 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { throw StorageErrorFactory.getEntityNotFound(context); } - if (ifMatch === undefined || ifMatch === "*" || doc.eTag === ifMatch) { + // if match is URL encoded from the clients, match URL encoding + // this does not always seem to be consisten... + const encodedEtag = doc.eTag.replace(":", "%3A").replace(":", "%3A"); + let encodedIfMatch: string | undefined; + if (ifMatch !== undefined) { + encodedIfMatch = ifMatch!.replace(":", "%3A").replace(":", "%3A"); + } + if ( + encodedIfMatch === undefined || + encodedIfMatch === "*" || + (encodedIfMatch !== undefined && encodedEtag === encodedIfMatch) + ) { const mergedDEntity: Entity = { ...doc, ...entity, diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 1caecf709..336f49483 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -16,19 +16,47 @@ import { // Set true to enable debug log configLogger(false); +/** + * Creates an entity for tests, with a randomized row key, + * to avoid conflicts on inserts. + * + * @return {*} {TestEntity} + */ +function createBasicEntityForTest(): TestEntity { + return new TestEntity("part1", getUniqueName("row"), "value1"); +} + +class TestEntity { + public PartitionKey: Azure.TableUtilities.entityGenerator.EntityProperty< + string + >; + public RowKey: Azure.TableUtilities.entityGenerator.EntityProperty; + public myValue: Azure.TableUtilities.entityGenerator.EntityProperty; + constructor(part: string, row: string, value: string) { + this.PartitionKey = eg.String(part); + this.RowKey = eg.String(row); + this.myValue = eg.String(value); + } +} + +const eg = Azure.TableUtilities.entityGenerator; + describe("table Entity APIs test", () => { // TODO: Create a server factory as tests utils const protocol = "http"; const host = "127.0.0.1"; const port = 11002; const metadataDbPath = "__tableTestsStorage__"; - + const enableDebugLog: boolean = true; + const debugLogPath: string = "g:/debug.log"; const config = new TableConfiguration( host, port, metadataDbPath, + enableDebugLog, false, - false + undefined, + debugLogPath ); let server: TableServer; @@ -39,6 +67,8 @@ describe("table Entity APIs test", () => { `AccountKey=${sharedKey};TableEndpoint=${protocol}://${host}:${port}/${accountName};`; const tableService = Azure.createTableService(connectionString); + // ToDo: added due to problem with batch responses not finishing properly - Need to investigate batch response + tableService.enableGlobalHttpAgent = true; let tableName: string = getUniqueName("table"); @@ -416,32 +446,28 @@ describe("table Entity APIs test", () => { Prefer: "return-content", accept: "application/json;odata=fullmetadata" }; - tableService.insertOrReplaceEntity( - tableName, - { - PartitionKey: "part1", - RowKey: "row6", - myValue: "newValue" - }, - (updateError, updateResult, updateResponse) => { - if (updateError) { - assert.ifError(updateError); - done(); - } else { - assert.equal(updateResponse.statusCode, 204); // No content - // TODO When QueryEntity is done - validate Entity Properties - done(); + const upsertEntity = createBasicEntityForTest(); + tableService.insertEntity(tableName, upsertEntity, () => { + upsertEntity.myValue._ = "updated"; + tableService.insertOrReplaceEntity( + tableName, + upsertEntity, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 204); // No content + // TODO When QueryEntity is done - validate Entity Properties + done(); + } } - } - ); + ); + }); }); it("Insert or Merge on an Entity that exists, @loki", (done) => { - const entityInsert = { - PartitionKey: "part1", - RowKey: "merge1", - myValue: "oldValue" - }; + const entityInsert = createBasicEntityForTest(); requestOverride.headers = { Prefer: "return-content", accept: "application/json;odata=fullmetadata" @@ -450,16 +476,12 @@ describe("table Entity APIs test", () => { tableName, entityInsert, (error, result, insertresponse) => { - const entityUpdate = { - PartitionKey: "part1", - RowKey: "merge1", - mergeValue: "newValue" - }; + entityInsert.myValue._ = "new value"; if (!error) { requestOverride.headers = {}; tableService.insertOrMergeEntity( tableName, - entityUpdate, + entityInsert, (updateError, updateResult, updateResponse) => { if (!updateError) { assert.equal(updateResponse.statusCode, 204); // Precondition succeeded @@ -503,4 +525,459 @@ describe("table Entity APIs test", () => { } ); }); + + // Start of Batch Tests: + it("Simple Insert Or Replace of a SINGLE entity as a BATCH, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + + const batchEntity1 = createBasicEntityForTest(); + + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.addOperation("INSERT_OR_REPLACE", batchEntity1); // resulting in PUT + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result) => { + if (error) { + assert.ifError(error); + } else if (result) { + const entity: TestEntity = result; + assert.equal(entity.myValue._, batchEntity1.myValue._); + } + done(); + } + ); + } + } + ); + }); + + it("Simple batch test: Inserts multiple entities as a batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const batchEntity1 = createBasicEntityForTest(); + const batchEntity2 = createBasicEntityForTest(); + const batchEntity3 = createBasicEntityForTest(); + + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.addOperation("INSERT", batchEntity1, { echoContent: true }); + entityBatch.addOperation("INSERT", batchEntity2, { echoContent: true }); + entityBatch.addOperation("INSERT", batchEntity3, { echoContent: true }); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); // No content + // Now that QueryEntity is done - validate Entity Properties as follows: + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result) => { + const entity: TestEntity = result; + assert.equal(entity.myValue._, batchEntity1.myValue._); + done(); + } + ); + } + } + ); + }); + + it("Simple batch test: Delete multiple entities as a batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + // First insert multiple entities to delete + const batchEntity1 = createBasicEntityForTest(); + const batchEntity2 = createBasicEntityForTest(); + const batchEntity3 = createBasicEntityForTest(); + + assert.notDeepEqual( + batchEntity1.RowKey, + batchEntity2.RowKey, + "failed to create unique test entities 1 & 2" + ); + assert.notDeepEqual( + batchEntity1.RowKey, + batchEntity3.RowKey, + "failed to create unique test entities 2 & 3" + ); + + const insertEntityBatch: Azure.TableBatch = new Azure.TableBatch(); + insertEntityBatch.addOperation("INSERT", batchEntity1, { + echoContent: true + }); + insertEntityBatch.addOperation("INSERT", batchEntity2, { + echoContent: true + }); + insertEntityBatch.addOperation("INSERT", batchEntity3, { + echoContent: true + }); + + const deleteEntityBatch: Azure.TableBatch = new Azure.TableBatch(); + deleteEntityBatch.deleteEntity(batchEntity1); + deleteEntityBatch.deleteEntity(batchEntity2); + deleteEntityBatch.deleteEntity(batchEntity3); + + tableService.executeBatch( + tableName, + insertEntityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); // No content + // Now that QueryEntity is done - validate Entity Properties as follows: + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result) => { + if (error) { + assert.notEqual(error, null); + done(); + } + const entity: TestEntity = result; + assert.equal(entity.myValue._, batchEntity1.myValue._); + + // now that we have confirmed that our test entities are created, we can try to delete them + tableService.executeBatch( + tableName, + deleteEntityBatch, + ( + deleteUpdateError, + deleteUpdateResult, + deleteUpdateResponse + ) => { + if (deleteUpdateError) { + assert.ifError(deleteUpdateError); + done(); + } else { + assert.equal(deleteUpdateResponse.statusCode, 202); // No content + // Now that QueryEntity is done - validate Entity Properties as follows: + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (finalRetrieveError, finalRetrieveResult) => { + const retrieveError: StorageError = finalRetrieveError as StorageError; + assert.equal( + retrieveError.statusCode, + 404, + "status code was not equal to 404!" + ); + done(); + } + ); + } + } + ); + } + ); + } + } + ); + }); + + it("Insert Or Replace multiple entities as a batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + + const batchEntity1 = createBasicEntityForTest(); + const batchEntity2 = createBasicEntityForTest(); + const batchEntity3 = createBasicEntityForTest(); + + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.addOperation("INSERT_OR_REPLACE", batchEntity1); + entityBatch.addOperation("INSERT_OR_REPLACE", batchEntity2); + entityBatch.addOperation("INSERT_OR_REPLACE", batchEntity3); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result) => { + if (error) { + assert.ifError(error); + } else if (result) { + const entity: TestEntity = result; + assert.equal(entity.myValue._, batchEntity1.myValue._); + } + done(); + } + ); + } + } + ); + }); + + it("Insert Or Merge multiple entities as a batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const batchEntity1 = createBasicEntityForTest(); + const batchEntity2 = createBasicEntityForTest(); + const batchEntity3 = createBasicEntityForTest(); + + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.addOperation("INSERT_OR_MERGE", batchEntity1); + entityBatch.addOperation("INSERT_OR_MERGE", batchEntity2); + entityBatch.addOperation("INSERT_OR_MERGE", batchEntity3); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result) => { + if (error) { + assert.ifError(error); + } else if (result) { + const entity: TestEntity = result; + assert.equal(entity.myValue._, batchEntity1.myValue._); + } + done(); + } + ); + } + } + ); + }); + + it("Insert and Update entity via a batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const batchEntity1 = createBasicEntityForTest(); + + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.addOperation("INSERT", batchEntity1, { echoContent: true }); + batchEntity1.myValue._ = "value2"; + entityBatch.replaceEntity(batchEntity1); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result) => { + if (error) { + assert.ifError(error); + done(); + } else if (result) { + const entity: TestEntity = result; + assert.equal(entity.myValue._, batchEntity1.myValue._); + } + done(); + } + ); + } + } + ); + }); + + it("Insert and Merge entity via a batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const batchEntity1 = createBasicEntityForTest(); + + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.addOperation("INSERT", batchEntity1, { echoContent: true }); + batchEntity1.myValue._ = "value2"; + entityBatch.mergeEntity(batchEntity1); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result) => { + if (error) { + assert.ifError(error); + } else if (result) { + const entity: TestEntity = result; + assert.equal(entity.myValue._, batchEntity1.myValue._); + } + done(); + } + ); + } + } + ); + }); + + it("Insert and Delete entity via a batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const batchEntity1 = createBasicEntityForTest(); + + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.addOperation("INSERT", batchEntity1, { echoContent: true }); + entityBatch.deleteEntity(batchEntity1); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result) => { + const retrieveError: StorageError = error as StorageError; + assert.equal( + retrieveError.statusCode, + 404, + "status code was not equal to 404!" + ); + done(); + } + ); + } + } + ); + }); + + it("Query / Retrieve single entity via a batch, requestion Options undefined / default @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const batchEntity1 = createBasicEntityForTest(); + + tableService.insertEntity(tableName, batchEntity1, (error, result) => { + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.retrieveEntity( + batchEntity1.PartitionKey._, + batchEntity1.RowKey._ + ); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + const batchRetrieveEntityResult = updateResponse.body + ? updateResponse.body + : ""; + assert.notEqual(batchRetrieveEntityResult.indexOf("value1"), -1); + done(); + } + } + ); + }); + }); + + it("Single Delete entity via a batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const batchEntity1 = createBasicEntityForTest(); + + tableService.insertEntity(tableName, batchEntity1, () => { + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.deleteEntity(batchEntity1); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error: any, result) => { + assert.equal( + error.statusCode, + 404, + "status code was not equal to 404!" + ); + done(); + } + ); + } + } + ); + }); + }); }); diff --git a/tests/table/unit/deserialization.unit.tests.ts b/tests/table/unit/deserialization.unit.tests.ts new file mode 100644 index 000000000..7138d07a6 --- /dev/null +++ b/tests/table/unit/deserialization.unit.tests.ts @@ -0,0 +1,345 @@ +// Unit Tests for serialization +import * as assert from "assert"; +import { BatchType } from "../../../src/common/batch/BatchOperation"; +import BatchRequestHeaders from "../../../src/common/batch/BatchRequestHeaders"; +import { BatchSerialization } from "../../../src/common/batch/BatchSerialization"; +import { TableBatchSerialization } from "../../../src/table/batch/TableBatchSerialization"; +import SerializationRequestMockStrings from "./mock.request.serialization.strings"; + +describe("batch deserialization unit tests, these are not the API integration tests:", () => { + it("deserializes, mock table batch request containing 3 insert requests correctly", (done) => { + const requestString = + SerializationRequestMockStrings.Sample3InsertsUsingSDK; + const serializer = new TableBatchSerialization(); + const batchOperationArray = serializer.deserializeBatchRequest( + requestString + ); + + assert.equal( + batchOperationArray.length, + 3, + "failed to deserialize correct number of operations" + ); + assert.equal(batchOperationArray[0].batchType, BatchType.table); + assert.equal( + batchOperationArray[0].httpMethod, + "POST", + "wrong HTTP Method parsed" + ); + assert.equal( + batchOperationArray[0].path, + "table160837408807101776", + "wrong path parsed" + ); + assert.equal( + batchOperationArray[0].uri, + "http://127.0.0.1:11002/devstoreaccount1/table160837408807101776", + "wrong url parsed" + ); + assert.equal( + batchOperationArray[0].jsonRequestBody, + '{"PartitionKey":"part1","RowKey":"row160837408812000231","myValue":"value1"}', + "wrong jsonBody parsed" + ); + // Second Batch Operation + assert.equal(batchOperationArray[1].batchType, BatchType.table); + assert.equal( + batchOperationArray[1].httpMethod, + "POST", + "wrong HTTP Method parsed" + ); + assert.equal( + batchOperationArray[1].path, + "table160837408807101776", + "wrong path parsed" + ); + assert.equal( + batchOperationArray[1].uri, + "http://127.0.0.1:11002/devstoreaccount1/table160837408807101776", + "wrong url parsed" + ); + assert.equal( + batchOperationArray[1].jsonRequestBody, + '{"PartitionKey":"part1","RowKey":"row160837408812008370","myValue":"value1"}', + "wrong jsonBody parsed" + ); + // Third Batch Operation + assert.equal(batchOperationArray[2].batchType, BatchType.table); + assert.equal( + batchOperationArray[2].httpMethod, + "POST", + "wrong HTTP Method parsed" + ); + assert.equal( + batchOperationArray[2].path, + "table160837408807101776", + "wrong path parsed" + ); + assert.equal( + batchOperationArray[2].uri, + "http://127.0.0.1:11002/devstoreaccount1/table160837408807101776", + "wrong url parsed" + ); + assert.equal( + batchOperationArray[2].jsonRequestBody, + '{"PartitionKey":"part1","RowKey":"row160837408812003154","myValue":"value1"}', + "wrong jsonBody parsed" + ); + done(); + }); + + it("deserializes, mock table batch request containing a query correctly", (done) => { + const requestString = SerializationRequestMockStrings.Sample1QueryUsingSDK; + const serializer = new TableBatchSerialization(); + const batchOperationArray = serializer.deserializeBatchRequest( + requestString + ); + + // this first test is currently a stupid test, as I control the type within the code + // we want to test that we have deserialized the operation. + assert.equal(batchOperationArray[0].batchType, BatchType.table); + assert.equal( + batchOperationArray[0].httpMethod, + "GET", + "wrong HTTP Method parsed" + ); + assert.equal( + batchOperationArray[0].path, + "table160837567141205013", + "wrong path parsed" + ); + assert.equal( + batchOperationArray[0].uri, + "http://127.0.0.1:11002/devstoreaccount1/table160837567141205013(PartitionKey=%27part1%27,RowKey=%27row160837567145205850%27)", + "wrong url parsed" + ); + assert.equal( + batchOperationArray[0].jsonRequestBody, + "", + "wrong jsonBody parsed" + ); + done(); + }); + + it("deserializes, mock table batch request containing insert and merge correctly", (done) => { + const requestString = + SerializationRequestMockStrings.SampleInsertThenMergeUsingSDK; + const serializer = new TableBatchSerialization(); + const batchOperationArray = serializer.deserializeBatchRequest( + requestString + ); + + // First Batch Operation is an insert. + assert.equal(batchOperationArray[0].batchType, BatchType.table); + assert.equal( + batchOperationArray[0].httpMethod, + "POST", + "wrong HTTP Method parsed" + ); + assert.equal( + batchOperationArray[0].path, + "table160837770303307822", + "wrong path parsed" + ); + assert.equal( + batchOperationArray[0].uri, + "http://127.0.0.1:11002/devstoreaccount1/table160837770303307822", + "wrong url parsed" + ); + assert.equal( + batchOperationArray[0].jsonRequestBody, + '{"PartitionKey":"part1","RowKey":"row160837770307508823","myValue":"value2"}', + "wrong jsonBody parsed" + ); + // Second Batch Operation is a merge + assert.equal(batchOperationArray[1].batchType, BatchType.table); + assert.equal( + batchOperationArray[1].httpMethod, + "MERGE", + "wrong HTTP Method parsed" + ); + assert.equal( + batchOperationArray[1].path, + "table160837770303307822", + "wrong path parsed" + ); + assert.equal( + batchOperationArray[1].uri, + "http://127.0.0.1:11002/devstoreaccount1/table160837770303307822(PartitionKey=%27part1%27,RowKey=%27row160837770307508823%27)", + "wrong url parsed" + ); + assert.equal( + batchOperationArray[1].jsonRequestBody, + '{"PartitionKey":"part1","RowKey":"row160837770307508823","myValue":"valueMerge"}', + "wrong jsonBody parsed" + ); + done(); + }); + + it("deserializes, mock table batch request containing 3 deletes correctly", (done) => { + const requestString = + SerializationRequestMockStrings.Sample3DeletesUsingSDK; + const serializer = new TableBatchSerialization(); + const batchOperationArray = serializer.deserializeBatchRequest( + requestString + ); + + // First Batch Operation is an insert. + assert.equal(batchOperationArray[0].batchType, BatchType.table); + assert.equal( + batchOperationArray[0].httpMethod, + "DELETE", + "wrong HTTP Method parsed" + ); + assert.equal( + batchOperationArray[0].path, + "table161216830457901592", + "wrong path parsed" + ); + assert.equal( + batchOperationArray[0].uri, + "http://127.0.0.1:11002/devstoreaccount1/table161216830457901592(PartitionKey=%27part1%27,RowKey=%27row161216830462208585%27)", + "wrong url parsed" + ); + assert.equal( + batchOperationArray[0].jsonRequestBody, + "", + "wrong jsonBody parsed" + ); + // Second Batch Operation is a Delete + assert.equal(batchOperationArray[1].batchType, BatchType.table); + assert.equal( + batchOperationArray[1].httpMethod, + "DELETE", + "wrong HTTP Method parsed" + ); + assert.equal( + batchOperationArray[1].path, + "table161216830457901592", + "wrong path parsed" + ); + assert.equal( + batchOperationArray[1].uri, + "http://127.0.0.1:11002/devstoreaccount1/table161216830457901592(PartitionKey=%27part1%27,RowKey=%27row161216830462204546%27)", + "wrong url parsed" + ); + assert.equal( + batchOperationArray[1].jsonRequestBody, + "", + "wrong jsonBody parsed" + ); + done(); + }); + + it("deserializes, mock durable function request correctly", (done) => { + const requestString = + SerializationRequestMockStrings.BatchDurableE1HelloRequestString; + const serializer = new TableBatchSerialization(); + const batchOperationArray = serializer.deserializeBatchRequest( + requestString + ); + + // There are 5 operations in the batch + assert.equal(batchOperationArray.length, 5); + // First Batch Operation is an insert. + assert.equal(batchOperationArray[0].batchType, BatchType.table); + + done(); + }); + + // boundary tests + it("finds the \\r\\n line ending boundary in a durable functions call", (done) => { + const serializationBase = new BatchSerialization(); + // extract batchBoundary + serializationBase.extractLineEndings( + SerializationRequestMockStrings.BatchDurableE1HelloRequestString + ); + assert.equal(serializationBase.lineEnding, "\r\n"); + done(); + }); + + it("finds the \\n line ending boundary in an SDK call", (done) => { + const serializationBase = new BatchSerialization(); + // extract batchBoundary + serializationBase.extractLineEndings( + SerializationRequestMockStrings.Sample3InsertsUsingSDK + ); + assert.equal(serializationBase.lineEnding, "\n"); + done(); + }); + + it("finds the batch boundary in a durable functions call", (done) => { + const serializationBase = new BatchSerialization(); + // extract batchBoundary + serializationBase.extractBatchBoundary( + SerializationRequestMockStrings.BatchDurableE1HelloRequestString + ); + assert.equal( + serializationBase.batchBoundary, + "--batch_35c74636-e91e-4c4f-9ab1-906881bf7d9d" + ); + done(); + }); + + it("finds the changeset boundary in a durable functions call", (done) => { + const serializationBase = new BatchSerialization(); + serializationBase.extractChangeSetBoundary( + SerializationRequestMockStrings.BatchDurableE1HelloRequestString + ); + assert.equal( + serializationBase.changesetBoundary, + "changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0" + ); + done(); + }); + + it("finds the batch boundary in a single retrieve entity call", (done) => { + const serializationBase = new BatchSerialization(); + // extract batchBoundary + serializationBase.extractBatchBoundary( + SerializationRequestMockStrings.BatchQueryWithPartitionKeyAndRowKeyRequest + ); + assert.equal( + serializationBase.batchBoundary, + "--batch_d54a6553104c5b65f259aa178d324ebf" + ); + done(); + }); + + it("finds the changeset boundary in a single retrieve entity call", (done) => { + const serializationBase = new BatchSerialization(); + serializationBase.extractChangeSetBoundary( + SerializationRequestMockStrings.BatchQueryWithPartitionKeyAndRowKeyRequest + ); + assert.equal( + serializationBase.changesetBoundary, + "--batch_d54a6553104c5b65f259aa178d324ebf" + ); + done(); + }); + + it("finds the changeset boundary in a non guid form", (done) => { + const serializationBase = new BatchSerialization(); + serializationBase.extractChangeSetBoundary( + SerializationRequestMockStrings.BatchNonGuidBoundaryShortString + ); + assert.equal(serializationBase.changesetBoundary, "blahblah"); + done(); + }); + + it("deserializes the headers correctly for a batch request", (done) => { + const sampleHeaders = [ + "HTTP/1.1\r", + "Accept: application/json;odata=minimalmetadata\r", + "Content-Type: application/json\r", + "Prefer: return-no-content\r", + "DataServiceVersion: 3.0;\r", + "\r", + "" + ]; + // const headers1 = new BatchRequestHeaders(sampleHeaders1); + const headers = new BatchRequestHeaders(sampleHeaders); + assert.equal(headers.header("prefer"), "return-no-content"); + done(); + }); +}); diff --git a/tests/table/unit/mock.request.serialization.strings.ts b/tests/table/unit/mock.request.serialization.strings.ts new file mode 100644 index 000000000..1793fbcaa --- /dev/null +++ b/tests/table/unit/mock.request.serialization.strings.ts @@ -0,0 +1,72 @@ +// Contains Mocks for Serialization Tests + +export default class SerializationRequestMockStrings { + // #################### + // Mocks for a batch of 3 Inserts using the Javascript SDK + // #################### + // prettier-ignore + public static Sample3InsertsUsingSDK: string ='--batch_7679a9f9b2dde130e791580c53508a5a\ncontent-type: multipart/mixed;charset="utf-8";boundary=changeset_7679a9f9b2dde130e791580c53508a5a\n\n--changeset_7679a9f9b2dde130e791580c53508a5a\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nPOST http://127.0.0.1:11002/devstoreaccount1/table160837408807101776 HTTP/1.1\nPrefer: return-content\ncontent-length: 76\ncontent-type: application/json;type=entry\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n{"PartitionKey":"part1","RowKey":"row160837408812000231","myValue":"value1"}\n--changeset_7679a9f9b2dde130e791580c53508a5a\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nPOST http://127.0.0.1:11002/devstoreaccount1/table160837408807101776 HTTP/1.1\nPrefer: return-content\ncontent-length: 76\ncontent-type: application/json;type=entry\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\ncontent-id: 1\n\n{"PartitionKey":"part1","RowKey":"row160837408812008370","myValue":"value1"}\n--changeset_7679a9f9b2dde130e791580c53508a5a\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nPOST http://127.0.0.1:11002/devstoreaccount1/table160837408807101776 HTTP/1.1\nPrefer: return-content\ncontent-length: 76\ncontent-type: application/json;type=entry\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\ncontent-id: 2\n\n{"PartitionKey":"part1","RowKey":"row160837408812003154","myValue":"value1"}\n--changeset_7679a9f9b2dde130e791580c53508a5a--\n--batch_7679a9f9b2dde130e791580c53508a5a--'; + + // #################### + // Mocks for a batch containing single retrieve entity using the Javascript SDK + // #################### + // prettier-ignore + public static Sample1QueryUsingSDK: string = "--batch_d737e1b79cb362526a8b4a13d46d6fc3\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nGET http://127.0.0.1:11002/devstoreaccount1/table160837567141205013(PartitionKey=%27part1%27,RowKey=%27row160837567145205850%27) HTTP/1.1\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n--batch_d737e1b79cb362526a8b4a13d46d6fc3--"; + + // #################### + // Mocks for a batch with insert then merge using the Javascript SDK + // #################### + // prettier-ignore + public static SampleInsertThenMergeUsingSDK: string = '--batch_aa71f86e6ed5d85b178b2a28cbb61f97\ncontent-type: multipart/mixed;charset="utf-8";boundary=changeset_aa71f86e6ed5d85b178b2a28cbb61f97\n\n--changeset_aa71f86e6ed5d85b178b2a28cbb61f97\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nPOST http://127.0.0.1:11002/devstoreaccount1/table160837770303307822 HTTP/1.1\nPrefer: return-content\ncontent-length: 76\ncontent-type: application/json;type=entry\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n{"PartitionKey":"part1","RowKey":"row160837770307508823","myValue":"value2"}\n--changeset_aa71f86e6ed5d85b178b2a28cbb61f97\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nMERGE http://127.0.0.1:11002/devstoreaccount1/table160837770303307822(PartitionKey=%27part1%27,RowKey=%27row160837770307508823%27) HTTP/1.1\nif-match: *\ncontent-length: 76\ncontent-type: application/json;type=entry\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\ncontent-id: 1\n\n{"PartitionKey":"part1","RowKey":"row160837770307508823","myValue":"valueMerge"}\n--changeset_aa71f86e6ed5d85b178b2a28cbb61f97--\n--batch_aa71f86e6ed5d85b178b2a28cbb61f97--'; + + // #################### + // Mocks for a batch of 3 Deletes using the Javascript SDK + // #################### + // prettier-ignore + public static Sample3DeletesUsingSDK: string = '--batch_2d60b21ff9edaf2bc1bc4f60664c0283\ncontent-type: multipart/mixed;charset="utf-8";boundary=changeset_2d60b21ff9edaf2bc1bc4f60664c0283\n\n--changeset_2d60b21ff9edaf2bc1bc4f60664c0283\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nDELETE http://127.0.0.1:11002/devstoreaccount1/table161216830457901592(PartitionKey=%27part1%27,RowKey=%27row161216830462208585%27) HTTP/1.1\nif-match: *\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n\n--changeset_2d60b21ff9edaf2bc1bc4f60664c0283\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nDELETE http://127.0.0.1:11002/devstoreaccount1/table161216830457901592(PartitionKey=%27part1%27,RowKey=%27row161216830462204546%27) HTTP/1.1\nif-match: *\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\ncontent-id: 1\n\n\n--changeset_2d60b21ff9edaf2bc1bc4f60664c0283\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nDELETE http://127.0.0.1:11002/devstoreaccount1/table161216830457901592(PartitionKey=%27part1%27,RowKey=%27row161216830462201168%27) HTTP/1.1\nif-match: *\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\ncontent-id: 2\n\n\n--changeset_2d60b21ff9edaf2bc1bc4f60664c0283--\n--batch_2d60b21ff9edaf2bc1bc4f60664c0283--'; + + // #################### + // Mocks for Query with Partition and Row Key (Retrieve single entity) + // #################### + // prettier-ignore + public static BatchQueryWithPartitionKeyAndRowKeyRequest: string = + "--batch_d54a6553104c5b65f259aa178d324ebf\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nGET http://127.0.0.1:11002/devstoreaccount1/table161289070041408231(PartitionKey=%27part1%27,RowKey=%27row161289070046904593%27) HTTP/1.1\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n--batch_d54a6553104c5b65f259aa178d324ebf--"; + + // #################### + // Mocks for Single Batch Insert or Replace + // #################### + public static BatchSingleInsertOrReplaceRequestString: string = + // "--batch_d691a4531b1f15df5b381893a422ead1\ncontent-type: multipart/mixed;charset=\"utf-8\";boundary=changeset_d691a4531b1f15df5b381893a422ead1\n\n--changeset_d691a4531b1f15df5b381893a422ead1\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nPUT http://127.0.0.1:11002/devstoreaccount1/table161311975539604802(PartitionKey=%27part1%27,RowKey=%27row161311975544100305%27) HTTP/1.1\ncontent-length: 76\ncontent-type: application/json;type=entry\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n{\"PartitionKey\":\"part1\",\"RowKey\":\"row161311975544100305\",\"myValue\":\"value1\"}\n--changeset_d691a4531b1f15df5b381893a422ead1--\n--batch_d691a4531b1f15df5b381893a422ead1--" + // prettier-ignore + "--batch_d691a4531b1f15df5b381893a422ead1\ncontent-type: multipart/mixed;charset=\"utf-8\";boundary=changeset_d691a4531b1f15df5b381893a422ead1\n\n--changeset_d691a4531b1f15df5b381893a422ead1\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nPUT http://127.0.0.1:11002/devstoreaccount1/table161311975539604802(PartitionKey=%27part1%27,RowKey=%27row161311975544100305%27) HTTP/1.1\ncontent-length: 76\ncontent-type: application/json;type=entry\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n{\"PartitionKey\":\"part1\",\"RowKey\":\"row161311975544100305\",\"myValue\":\"value1\"}\n--changeset_d691a4531b1f15df5b381893a422ead1--\n--batch_d691a4531b1f15df5b381893a422ead1--"; + + // #################### + // Mocks for Single Batch Insert or Replace + // #################### + public static BatchSingleDeleteRequestString: string = + // "--batch_45ff59679ba7159ade46401b1d670939\ncontent-type: multipart/mixed;charset=\"utf-8\";boundary=changeset_45ff59679ba7159ade46401b1d670939\n\n--changeset_45ff59679ba7159ade46401b1d670939\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nDELETE http://127.0.0.1:11002/devstoreaccount1/table161314571276801774(PartitionKey=%27part1%27,RowKey=%27row161314571280802822%27) HTTP/1.1\nif-match: *\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n\n--changeset_45ff59679ba7159ade46401b1d670939--\n--batch_45ff59679ba7159ade46401b1d670939--" + // prettier-ignore + "--batch_45ff59679ba7159ade46401b1d670939\ncontent-type: multipart/mixed;charset=\"utf-8\";boundary=changeset_45ff59679ba7159ade46401b1d670939\n\n--changeset_45ff59679ba7159ade46401b1d670939\ncontent-type: application/http\ncontent-transfer-encoding: binary\n\nDELETE http://127.0.0.1:11002/devstoreaccount1/table161314571276801774(PartitionKey=%27part1%27,RowKey=%27row161314571280802822%27) HTTP/1.1\nif-match: *\naccept: application/json;odata=minimalmetadata\nmaxdataserviceversion: 3.0;NetFx\n\n\n--changeset_45ff59679ba7159ade46401b1d670939--\n--batch_45ff59679ba7159ade46401b1d670939--"; + + // #################### + // Mocks for non GUID form boundaries + // #################### + public static BatchNonGuidBoundaryShortString: string = + // prettier-ignore + "--batch_blahblahblah\r\nContent-Type: multipart/mixed; boundary=blahblah\r\n\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory"; + + // #################### + // Mocks for Durable Functions Request in E1_HelloSequence + // #################### + public static BatchDurableE1HelloRequestString: string = + // "--batch_35c74636-e91e-4c4f-9ab1-906881bf7d9d\r\nContent-Type: multipart/mixed; boundary=changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\n\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='a572042d48964354b246501e57ac17a2',RowKey='0000000000000000') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"EventId\":-1,\"IsPlayed\":false,\"_Timestamp\":\"2021-02-25T07:58:15.2007575Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"OrchestratorStarted\",\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='a572042d48964354b246501e57ac17a2',RowKey='0000000000000001') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"Name\":\"E1_HelloSequence\",\"Version\":\"\",\"OrchestrationInstance\":\"{\\\"InstanceId\\\":\\\"a572042d48964354b246501e57ac17a2\\\",\\\"ExecutionId\\\":\\\"a747299cd8ec44a8a7ba9a73e93facb1\\\"}\",\"EventId\":-1,\"IsPlayed\":true,\"_Timestamp\":\"2021-02-25T07:58:15.0274133Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"ExecutionStarted\",\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='a572042d48964354b246501e57ac17a2',RowKey='0000000000000002') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"Name\":\"E1_SayHello\",\"Version\":\"\",\"EventId\":0,\"IsPlayed\":false,\"_Timestamp\":\"2021-02-25T07:58:15.2330710Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"TaskScheduled\",\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='a572042d48964354b246501e57ac17a2',RowKey='0000000000000003') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"EventId\":-1,\"IsPlayed\":false,\"_Timestamp\":\"2021-02-25T07:58:15.2338262Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"OrchestratorCompleted\",\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory() HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\nDataServiceVersion: 3.0;\r\n\r\n{\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\",\"IsCheckpointComplete\":true,\"CheckpointCompletedTimestamp\":\"2021-02-25T07:58:15.3606810Z\",\"CheckpointCompletedTimestamp@odata.type\":\"Edm.DateTime\",\"PartitionKey\":\"a572042d48964354b246501e57ac17a2\",\"RowKey\":\"sentinel\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0--\r\n--batch_35c74636-e91e-4c4f-9ab1-906881bf7d9d--\r\n" + // prettier-ignore + "--batch_35c74636-e91e-4c4f-9ab1-906881bf7d9d\r\nContent-Type: multipart/mixed; boundary=changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\n\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='a572042d48964354b246501e57ac17a2',RowKey='0000000000000000') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"EventId\":-1,\"IsPlayed\":false,\"_Timestamp\":\"2021-02-25T07:58:15.2007575Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"OrchestratorStarted\",\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='a572042d48964354b246501e57ac17a2',RowKey='0000000000000001') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"Name\":\"E1_HelloSequence\",\"Version\":\"\",\"OrchestrationInstance\":\"{\\\"InstanceId\\\":\\\"a572042d48964354b246501e57ac17a2\\\",\\\"ExecutionId\\\":\\\"a747299cd8ec44a8a7ba9a73e93facb1\\\"}\",\"EventId\":-1,\"IsPlayed\":true,\"_Timestamp\":\"2021-02-25T07:58:15.0274133Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"ExecutionStarted\",\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='a572042d48964354b246501e57ac17a2',RowKey='0000000000000002') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"Name\":\"E1_SayHello\",\"Version\":\"\",\"EventId\":0,\"IsPlayed\":false,\"_Timestamp\":\"2021-02-25T07:58:15.2330710Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"TaskScheduled\",\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='a572042d48964354b246501e57ac17a2',RowKey='0000000000000003') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"EventId\":-1,\"IsPlayed\":false,\"_Timestamp\":\"2021-02-25T07:58:15.2338262Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"OrchestratorCompleted\",\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory() HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\nDataServiceVersion: 3.0;\r\n\r\n{\"ExecutionId\":\"a747299cd8ec44a8a7ba9a73e93facb1\",\"IsCheckpointComplete\":true,\"CheckpointCompletedTimestamp\":\"2021-02-25T07:58:15.3606810Z\",\"CheckpointCompletedTimestamp@odata.type\":\"Edm.DateTime\",\"PartitionKey\":\"a572042d48964354b246501e57ac17a2\",\"RowKey\":\"sentinel\"}\r\n--changeset_0ac4036e-9ea9-4dfc-90c3-66a95213b6b0--\r\n--batch_35c74636-e91e-4c4f-9ab1-906881bf7d9d--\r\n"; + + // #################### + // Mocks for from Durable Function request + // #################### + public static BatchDurableE1HelloFiddlerRequestString: string = + // prettier-ignore + "--batch_e54c543a-639f-4b5d-b80e-3172493f797d\r\nContent-Type: multipart/mixed; boundary=changeset_43b7c7d4-eaba-498d-8946-cd778baf7800\r\n\r\n--changeset_43b7c7d4-eaba-498d-8946-cd778baf7800\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://ipv4.fiddler:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='7219c1f2e2674f249bf9589d31ab3c6e',RowKey='0000000000000000') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"EventId\":-1,\"IsPlayed\":false,\"_Timestamp\":\"2021-03-01T21:34:02.3688955Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"OrchestratorStarted\",\"ExecutionId\":\"17f0d39b6bd44086a6d5231caa6b06de\"}\r\n--changeset_43b7c7d4-eaba-498d-8946-cd778baf7800\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://ipv4.fiddler:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='7219c1f2e2674f249bf9589d31ab3c6e',RowKey='0000000000000001') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"Name\":\"E1_HelloSequence\",\"Version\":\"\",\"OrchestrationInstance\":\"{\\\"InstanceId\\\":\\\"7219c1f2e2674f249bf9589d31ab3c6e\\\",\\\"ExecutionId\\\":\\\"17f0d39b6bd44086a6d5231caa6b06de\\\"}\",\"EventId\":-1,\"IsPlayed\":true,\"_Timestamp\":\"2021-03-01T21:34:01.3090862Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"ExecutionStarted\",\"ExecutionId\":\"17f0d39b6bd44086a6d5231caa6b06de\"}\r\n--changeset_43b7c7d4-eaba-498d-8946-cd778baf7800\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://ipv4.fiddler:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='7219c1f2e2674f249bf9589d31ab3c6e',RowKey='0000000000000002') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"Name\":\"E1_SayHello\",\"Version\":\"\",\"EventId\":0,\"IsPlayed\":false,\"_Timestamp\":\"2021-03-01T21:34:02.5667562Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"TaskScheduled\",\"ExecutionId\":\"17f0d39b6bd44086a6d5231caa6b06de\"}\r\n--changeset_43b7c7d4-eaba-498d-8946-cd778baf7800\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://ipv4.fiddler:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='7219c1f2e2674f249bf9589d31ab3c6e',RowKey='0000000000000003') HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nDataServiceVersion: 3.0;\r\n\r\n{\"EventId\":-1,\"IsPlayed\":false,\"_Timestamp\":\"2021-03-01T21:34:02.5692738Z\",\"_Timestamp@odata.type\":\"Edm.DateTime\",\"EventType\":\"OrchestratorCompleted\",\"ExecutionId\":\"17f0d39b6bd44086a6d5231caa6b06de\"}\r\n--changeset_43b7c7d4-eaba-498d-8946-cd778baf7800\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://ipv4.fiddler:10002/devstoreaccount1/SampleHubVSHistory() HTTP/1.1\r\nAccept: application/json;odata=minimalmetadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\nDataServiceVersion: 3.0;\r\n\r\n{\"ExecutionId\":\"17f0d39b6bd44086a6d5231caa6b06de\",\"IsCheckpointComplete\":true,\"CheckpointCompletedTimestamp\":\"2021-03-01T21:34:02.9393490Z\",\"CheckpointCompletedTimestamp@odata.type\":\"Edm.DateTime\",\"PartitionKey\":\"7219c1f2e2674f249bf9589d31ab3c6e\",\"RowKey\":\"sentinel\"}\r\n--changeset_43b7c7d4-eaba-498d-8946-cd778baf7800--\r\n--batch_e54c543a-639f-4b5d-b80e-3172493f797d--\r\n"; +} diff --git a/tests/table/unit/mock.response.serialization.strings.ts b/tests/table/unit/mock.response.serialization.strings.ts new file mode 100644 index 000000000..8600fd6f5 --- /dev/null +++ b/tests/table/unit/mock.response.serialization.strings.ts @@ -0,0 +1,54 @@ +// These are the strings we get from within VS Code when we debug a request to the service +// Full request includes batch boundaries +// Partial is only the inner batch response from the serializer +// we need to use prettier ignore to avoid it messing with the formatting of the Etag and other escaped values +export default class SerializationResponseMockStrings { + // #################### + // Mocks for Query with Partition Key and Row Key + // #################### + public static FullBatchQueryWithPartitionKeyAndRowKeyResponse: string = + '\ +--batchresponse_5f4cfbb9-f5fa-45f1-9c9b-04e2436cbf9a\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 200 OK\r\nDataServiceVersion: 3.0;\r\nContent-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nETag: W/"datetime\'2021-02-05T17%3A15%3A16.7935715Z\'"\r\n\r\n{"odata.metadata":"https://azuritetesttarget.table.core.windows.net/$metadata#TestingAzurite/@Element","odata.etag":"W/"datetime\'2021-02-05T17%3A15%3A16.7935715Z\'"","PartitionKey":"part1","RowKey":"row161254531681303585","Timestamp":"2021-02-05T17:15:16.7935715Z","myValue":"value1"}\r\n--batchresponse_5f4cfbb9-f5fa-45f1-9c9b-04e2436cbf9a--\r\n\ +'; + + public static EmptyHeaderMock: string = ""; + + public static PartialBatchQueryWithPartitionKeyAndRowKeyResponse: string = + '\ +\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 200 OK\r\nDataServiceVersion: 3.0;\r\nContent-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nETag: W/"datetime\'2021-02-05T17%3A15%3A16.7935715Z\'"\r\n\r\n{"odata.metadata":"https://azuritetesttarget.table.core.windows.net/$metadata#TestingAzurite/@Element","odata.etag":"W/"datetime\'2021-02-05T17%3A15%3A16.7935715Z\'"","PartitionKey":"part1","RowKey":"row161254531681303585","Timestamp":"2021-02-05T17:15:16.7935715Z","myValue":"value1"}\r\n\ +'; + + // #################### + // Mocks for Single Batch Insert or Replace + // #################### + public static FullBatchSingleInsertOrReplaceResponseString: string = + // "--batchresponse_247e73cd-0e49-4854-8aad-3badc34b3381\r\nContent-Type: multipart/mixed; boundary=changesetresponse_8ddf8e68-ca51-45bd-8c65-95fe1cc94164\r\n\r\n--changesetresponse_8ddf8e68-ca51-45bd-8c65-95fe1cc94164\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 1.0;\r\nETag: W/\"datetime'2021-02-12T08%3A28%3A27.47468Z'\"\r\n\r\n\r\n--changesetresponse_8ddf8e68-ca51-45bd-8c65-95fe1cc94164--\r\n--batchresponse_247e73cd-0e49-4854-8aad-3badc34b3381--\r\n" + // prettier-ignore + "--batchresponse_247e73cd-0e49-4854-8aad-3badc34b3381\r\nContent-Type: multipart/mixed; boundary=changesetresponse_8ddf8e68-ca51-45bd-8c65-95fe1cc94164\r\n\r\n--changesetresponse_8ddf8e68-ca51-45bd-8c65-95fe1cc94164\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 1.0;\r\nETag: W/\"datetime'2021-02-12T08%3A28%3A27.47468Z'\"\r\n\r\n\r\n--changesetresponse_8ddf8e68-ca51-45bd-8c65-95fe1cc94164--\r\n--batchresponse_247e73cd-0e49-4854-8aad-3badc34b3381--\r\n"; + + // manually changed to +DataServiceVersion: 3.0; + // Azure responds with +DataServiceVersion: 1.0 right now + public static PartialBatchSingleInsertOrReplaceResponseString: string = + // prettier-ignore + "Content-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 3.0;\r\nETag: W/\"datetime'2021-02-12T08%3A28%3A27.47468Z'\"\r\nLocation: http://127.0.0.1:11002/devstoreaccount1/table161311975539604802(PartitionKey=%27part1%27,RowKey=%27row161311975544100305%27)\r\nDataServiceId: http://127.0.0.1:11002/devstoreaccount1/table161311975539604802(PartitionKey=%27part1%27,RowKey=%27row161311975544100305%27)\r\n"; + + // #################### + // Mocks for Single Batch Delete + // #################### + // "--batchresponse_5920f66b-704c-4f0d-a1ba-a024f44e4754\r\nContent-Type: multipart/mixed; boundary=changesetresponse_a3dab894-5e6c-4f3d-877e-dc918125467e\r\n\r\n--changesetresponse_a3dab894-5e6c-4f3d-877e-dc918125467e\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 1.0;\r\n\r\n\r\n--changesetresponse_a3dab894-5e6c-4f3d-877e-dc918125467e--\r\n--batchresponse_5920f66b-704c-4f0d-a1ba-a024f44e4754--\r\n" + public static FullBatchSingleDeleteResponseString: string = + // pretier-ignore + "--batchresponse_5920f66b-704c-4f0d-a1ba-a024f44e4754\r\nContent-Type: multipart/mixed; boundary=changesetresponse_a3dab894-5e6c-4f3d-877e-dc918125467e\r\n\r\n--changesetresponse_a3dab894-5e6c-4f3d-877e-dc918125467e\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 1.0;\r\n\r\n\r\n--changesetresponse_a3dab894-5e6c-4f3d-877e-dc918125467e--\r\n--batchresponse_5920f66b-704c-4f0d-a1ba-a024f44e4754--\r\n"; + + // manually set dataserviceversion to 3.0, service responds with 1.0 + public static PartialBatchSingleDeleteResponseString: string = + // pretier-ignore + "Content-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 3.0;\r\n"; + + // #################### + // Mocks for from Durable Function response + // #################### + public static BatchDurableE1HelloFiddlerRequestString: string = + // prettier-ignore + "--batchresponse_8bcbf48d-085c-46c0-aa19-1bfd84164968\r\nContent-Type: multipart/mixed; boundary=changesetresponse_c1f6ce4f-453e-4ac1-a075-f8ccf9342b7f\r\n\r\n--changesetresponse_c1f6ce4f-453e-4ac1-a075-f8ccf9342b7f\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No ContentX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 1.0;\r\nETag: W/\"datetime'2021-03-01T21%3A34%3A03.093Z'\"\r\n\r\n\r\n--changesetresponse_c1f6ce4f-453e-4ac1-a075-f8ccf9342b7f\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 1.0;\r\nETag: W/\"datetime'2021-03-01T21%3A34%3A03.093Z'\"\r\n\r\n\r\n--changesetresponse_c1f6ce4f-453e-4ac1-a075-f8ccf9342b7f\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 1.0;\r\nETag: W/\"datetime'2021-03-01T21%3A34%3A03.097Z'\"\r\n\r\n\r\n--changesetresponse_c1f6ce4f-453e-4ac1-a075-f8ccf9342b7f\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nDataServiceVersion: 1.0;\r\nETag: W/\"datetime'2021-03-01T21%3A34%3A03.097Z'\"\r\n\r\n\r\n--changesetresponse_c1f6ce4f-453e-4ac1-a075-f8ccf9342b7f\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nPreference-Applied: return-no-content\r\nDataServiceVersion: 3.0;\r\nLocation: http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='7219c1f2e2674f249bf9589d31ab3c6e',RowKey='sentinel')\r\nDataServiceId: http://127.0.0.1:10002/devstoreaccount1/SampleHubVSHistory(PartitionKey='7219c1f2e2674f249bf9589d31ab3c6e',RowKey='sentinel')\r\nETag: W/\"datetime'2021-03-01T21%3A34%3A03.097Z'\"\r\n\r\n\r\n--changesetresponse_c1f6ce4f-453e-4ac1-a075-f8ccf9342b7f--\r\n--batchresponse_8bcbf48d-085c-46c0-aa19-1bfd84164968--\r\n"; +} diff --git a/tests/table/unit/mock.serialization.batchoperation.factory.ts b/tests/table/unit/mock.serialization.batchoperation.factory.ts new file mode 100644 index 000000000..7fa3719dc --- /dev/null +++ b/tests/table/unit/mock.serialization.batchoperation.factory.ts @@ -0,0 +1,75 @@ +import { BatchType } from "../../../src/common/batch/BatchOperation"; +import TableBatchOperation from "../../../src/table/batch/TableBatchOperation"; + +export default class SerializationBatchOperationFactory { + // These values are hard coded to the request string + public static GetBatchOperationMockForQueryEntityWithPartitionKeyAndRowKey( + headers: string + ): TableBatchOperation { + const operation = new TableBatchOperation(BatchType.table, headers); + operation.httpMethod = "GET"; + operation.jsonRequestBody = ""; + operation.parameters = ""; + operation.path = "table161289070041408231"; + operation.protocol = ""; + operation.rawHeaders = [ + "HTTP/1.1", + "accept: application/json;odata=minimalmetadata", + "maxdataserviceversion: 3.0;NetFx", + "", + "" + ]; + operation.uri = + "http://127.0.0.1:11002/devstoreaccount1/table161289070041408231(PartitionKey=%27part1%27,RowKey=%27row16128907004690459%27)"; + return operation; + } + + public static GetBatchOperationMockForInsertSingleEntity( + headers: string + ): TableBatchOperation { + const operation = new TableBatchOperation(BatchType.table, headers); + operation.httpMethod = "PUT"; + operation.jsonRequestBody = ""; + operation.parameters = ""; + operation.path = "table161289070041408231"; + operation.protocol = ""; + operation.jsonRequestBody = + '{"PartitionKey":"part1","RowKey":"row161311975544100305","myValue":"value1"}'; + operation.rawHeaders = [ + "HTTP/1.1", + "content-length: 76", + "content-type: application/json;type=entry", + "accept: application/json;odata=minimalmetadata", + "maxdataserviceversion: 3.0;NetFx", + "", + "" + ]; + operation.uri = + "http://127.0.0.1:11002/devstoreaccount1/table161311975539604802"; + return operation; + } + + public static GetBatchOperationMockForDeleteSingleEntity( + headers: string + ): TableBatchOperation { + const operation = new TableBatchOperation(BatchType.table, headers); + operation.httpMethod = "DELETE"; + operation.jsonRequestBody = ""; + operation.parameters = ""; + operation.path = "table161314571276801774"; + operation.protocol = ""; + operation.jsonRequestBody = ""; + // ToDo: Check behaviour without empty headers + operation.rawHeaders = [ + "HTTP/1.1", + "if-match: *", + "accept: application/json;odata=minimalmetadata", + "maxdataserviceversion: 3.0;NetFx", + "", + "" + ]; + operation.uri = + "http://127.0.0.1:11002/devstoreaccount1/table161314571276801774(PartitionKey=%27part1%27,RowKey=%27row161314571280802822%27)"; + return operation; + } +} diff --git a/tests/table/unit/mock.serialization.batchrequest.factory.ts b/tests/table/unit/mock.serialization.batchrequest.factory.ts new file mode 100644 index 000000000..031ac8cb7 --- /dev/null +++ b/tests/table/unit/mock.serialization.batchrequest.factory.ts @@ -0,0 +1,89 @@ +import BatchRequest from "../../../src/common/batch/BatchRequest"; +import SerializationResponseMockStrings from "./mock.response.serialization.strings"; +import SerializationBatchOperationFactory from "./mock.serialization.batchoperation.factory"; +import * as Models from "../../../src/table/generated/artifacts/models"; +import toReadableStream from "to-readable-stream"; + +export default class SerializationObjectForBatchRequestFactory { + public static GetBatchRequestForQueryWithPartitionandRowKeyResponseMock(): BatchRequest { + const mockRequest = new BatchRequest( + SerializationBatchOperationFactory.GetBatchOperationMockForQueryEntityWithPartitionKeyAndRowKey( + SerializationResponseMockStrings.EmptyHeaderMock + ) + ); + return mockRequest; + } + + public static GetBatchRequestForSingleInsertResponseMock(): BatchRequest { + const mockRequest = new BatchRequest( + SerializationBatchOperationFactory.GetBatchOperationMockForInsertSingleEntity( + SerializationResponseMockStrings.EmptyHeaderMock + ) + ); + return mockRequest; + } + + public static GetBatchRequestForSingleDeletetResponseMock(): BatchRequest { + const mockRequest = new BatchRequest( + SerializationBatchOperationFactory.GetBatchOperationMockForDeleteSingleEntity( + SerializationResponseMockStrings.EmptyHeaderMock + ) + ); + return mockRequest; + } + + // see GetBatchTableQueryEntitiesWithPartitionAndRowKeyResponseMock + // for a more complete set of response props we can set + // this mock does not need it + public static GetBatchOperationMockForSingleInsert() { + const responseObject = new Object() as Models.TableInsertEntityResponse; + // Etag in response should be W/\"datetime'2021-02-12T08%3A28%3A27.47468Z'\" + // prettier-ignore + responseObject.eTag = 'W/"datetime\'2021-02-12T08%3A28%3A27.47468Z\'"'; + responseObject.statusCode = 204; // no content + return responseObject as Models.TableInsertEntityResponse; + } + + public static GetBatchOperationMockForSingleDelete() { + const responseObject = new Object() as Models.TableDeleteEntityResponse; + // Etag in response should be W/\"datetime'2021-02-12T08%3A28%3A27.47468Z'\" + // prettier-ignore + responseObject.statusCode = 204; // no content + return responseObject as Models.TableDeleteEntityResponse; + } + + public static GetBatchTableQueryEntitiesWithPartitionAndRowKeyResponseMock() { + const responseObject = new Object() as Models.TableQueryEntitiesWithPartitionAndRowKeyResponse; + // If a client request id header is sent in the request, this header will be present in the + // response with the same value. + responseObject.clientRequestId = ""; + // This header uniquely identifies the request that was made and can be used for troubleshooting + // the request. + responseObject.requestId = ""; + // Indicates the version of the Table service used to execute the request. This header is + // returned for requests made against version 2009-09-19 and above. + responseObject.version = ""; + // UTC date/time value generated by the service that indicates the time at which the response was + // initiated. + responseObject.date = new Date(); + // UTC date/time value generated by the service that indicates the time at which the response was + // initiated + // code formatter / prettier is messing up the string format which messes the response + // prettier-ignore + responseObject.eTag = 'W/"datetime\'2021-02-05T17%3A15%3A16.7935715Z\'"'; + // This header contains the continuation token value for partition key. + responseObject.xMsContinuationNextPartitionKey = ""; + // This header contains the continuation token value for row key. + responseObject.xMsContinuationNextRowKey = ""; + responseObject.errorCode = ""; + // using module to-readable-stream + responseObject.body = toReadableStream( + '{"odata.metadata":"https://azuritetesttarget.table.core.windows.net/$metadata#TestingAzurite/@Element",\ +"odata.etag":"W/"datetime\'2021-02-05T17%3A15%3A16.7935715Z\'"","PartitionKey":"part1","RowKey":"row161254531681303585",\ +"Timestamp":"2021-02-05T17:15:16.7935715Z","myValue":"value1"}' + ); + responseObject.statusCode = 200; + + return responseObject as Models.TableQueryEntitiesWithPartitionAndRowKeyResponse; + } +} diff --git a/tests/table/unit/serialization.unit.tests.ts b/tests/table/unit/serialization.unit.tests.ts new file mode 100644 index 000000000..67f98eb4c --- /dev/null +++ b/tests/table/unit/serialization.unit.tests.ts @@ -0,0 +1,116 @@ +// Unit Tests for serialization +// ToDo: I know these are not all strictly Unit tests +// while we finalize the reverse engineering of the table API, +// there is a lot of refactoring. +// meaning that we are not 100% sure of the correct object schemas. +// once this is all complete, we can further refactor and clean up +// objects and tests. +import * as assert from "assert"; +import BatchTableDeleteEntityOptionalParams from "../../../src/table/batch/BatchTableDeleteEntityOptionalParams"; +import BatchTableInsertEntityOptionalParams from "../../../src/table/batch/BatchTableInsertEntityOptionalParams"; +import BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams from "../../../src/table/batch/BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams"; +import { TableBatchSerialization } from "../../../src/table/batch/TableBatchSerialization"; +import SerializationRequestMockStrings from "./mock.request.serialization.strings"; +import SerializationResponseMocks from "./mock.response.serialization.strings"; +import SerializationObjectForBatchRequestFactory from "./mock.serialization.batchrequest.factory"; + +describe("batch serialization unit tests, these are not the API integration tests:", () => { + it("serializes, mock table batch response to query with partition key and row key operation correctly", async () => { + // use the expected response string to compare the + const expectedResponseString = + SerializationResponseMocks.PartialBatchQueryWithPartitionKeyAndRowKeyResponse; + const serializer = new TableBatchSerialization(); + // first we need to ingest the serialized request string, which fills some props on the serializer + serializer.deserializeBatchRequest( + SerializationRequestMockStrings.BatchQueryWithPartitionKeyAndRowKeyRequest + ); + + const request = SerializationObjectForBatchRequestFactory.GetBatchRequestForQueryWithPartitionandRowKeyResponseMock(); + request.ingestOptionalParams( + new BatchTableQueryEntitiesWithPartitionAndRowKeyOptionalParams() + ); + + const serializedBatchOperationResponse = await serializer.serializeTableQueryEntityWithPartitionAndRowKeyBatchResponse( + request, + SerializationObjectForBatchRequestFactory.GetBatchTableQueryEntitiesWithPartitionAndRowKeyResponseMock() + ); + + const splitResponse = serializedBatchOperationResponse.split("\r\n"); + const splitExpected = expectedResponseString.split("\r\n"); + splitResponse.forEach((value) => { + if (value.length > 2) { + assert.notEqual( + splitExpected.indexOf(value), + -1, + "Could not find " + value + ); + } + }); + + // no closing "done()" callback in async test + }); + + it("serializes, mock table batch response to single insert", (done) => { + // use the expected response string to compare the request to + const expectedResponseString = + SerializationResponseMocks.PartialBatchSingleInsertOrReplaceResponseString; + const serializer = new TableBatchSerialization(); + // first we need to ingest the serialized request string, which fills some props on the serializer + serializer.deserializeBatchRequest( + SerializationRequestMockStrings.BatchSingleInsertOrReplaceRequestString + ); + + const request = SerializationObjectForBatchRequestFactory.GetBatchRequestForSingleInsertResponseMock(); + request.ingestOptionalParams(new BatchTableInsertEntityOptionalParams()); + + const serializedBatchOperationResponse = serializer.serializeTableInsertEntityBatchResponse( + request, + SerializationObjectForBatchRequestFactory.GetBatchOperationMockForSingleInsert() + ); + + const splitResponse = serializedBatchOperationResponse.split("\r\n"); + const splitExpected = expectedResponseString.split("\r\n"); + splitExpected.forEach((value) => { + if (value.length > 2) { + assert.notEqual( + splitResponse.indexOf(value), + -1, + "Could not find " + value + " in serialized response." + ); + } + }); + done(); + }); + + it("serializes, mock table batch response to single delete", async () => { + // use the expected response string to compare the request to + // ToDo: Do we need partial or full? Currently Using full + const expectedResponseString = + SerializationResponseMocks.PartialBatchSingleDeleteResponseString; + const serializer = new TableBatchSerialization(); + // first we need to ingest the serialized request string, which fills some props on the serializer + serializer.deserializeBatchRequest( + SerializationRequestMockStrings.BatchSingleDeleteRequestString + ); + + const request = SerializationObjectForBatchRequestFactory.GetBatchRequestForSingleDeletetResponseMock(); + request.ingestOptionalParams(new BatchTableDeleteEntityOptionalParams()); + + const serializedBatchOperationResponse = serializer.serializeTableDeleteEntityBatchResponse( + request, + SerializationObjectForBatchRequestFactory.GetBatchOperationMockForSingleDelete() + ); + + const splitResponse = serializedBatchOperationResponse.split("\r\n"); + const splitExpected = expectedResponseString.split("\r\n"); + splitExpected.forEach((value) => { + if (value.length > 2) { + assert.notEqual( + splitResponse.indexOf(value), + -1, + "Could not find " + value + " in serialized response." + ); + } + }); + }); +}); From 2a26d01d8e2ae4cbfd160e0b6d86e7d907bcfe69 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Mon, 29 Mar 2021 12:31:13 +0200 Subject: [PATCH 35/57] updated package-lock.json after merge --- package-lock.json | 80 ++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3193fdf9d..faac23109 100644 --- a/package-lock.json +++ b/package-lock.json @@ -555,6 +555,12 @@ "@types/node": "*" } }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, "@types/range-parser": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", @@ -4012,6 +4018,12 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -4125,6 +4137,12 @@ "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, "linkify-it": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", @@ -4197,36 +4215,6 @@ "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", "dev": true }, - "listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^2.3.0", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - } - } - }, - "listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", - "dev": true - }, "listr-update-renderer": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", @@ -4841,15 +4829,6 @@ "which": "^1.2.10" } }, - "npm-path": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", - "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", - "dev": true, - "requires": { - "which": "^1.2.10" - } - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -5079,6 +5058,23 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -6792,6 +6788,12 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, "yargs": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz", From 040ef9b5de657554e48fcfbddf8bcb82e8c33b99 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Mon, 29 Mar 2021 16:58:44 +0200 Subject: [PATCH 36/57] Update Dockerfile Making sure that "npm ci" is after "Copy" cmds in Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index e425712a4..c35fb1dc0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,12 +7,12 @@ WORKDIR /opt/azurite # Install dependencies first COPY *.json LICENSE NOTICE.txt ./ -RUN npm config set unsafe-perm=true && \ - npm ci # Copy the source code and build the app COPY src ./src COPY tests ./tests +RUN npm config set unsafe-perm=true && \ + npm ci RUN npm run build && \ npm install -g --loglevel verbose From efdec52f97fc726200c87d6bae9f497030934366 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Tue, 30 Mar 2021 14:39:01 +0800 Subject: [PATCH 37/57] Update ChangeLog.md --- ChangeLog.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 67a37b6b6..a3ec75e5c 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,9 +4,8 @@ ## Upcoming Release -## 2021.03 Version 3.11.0-table-alpha.1 +Table: -- First Alpha version of Azurite V3 Table. - Allow empty RowKey in an entity. ## 2021.2 Version 3.11.0 @@ -30,6 +29,10 @@ Blob: - Fix an issue that snapshot time is omitted in get block list. - Fix an issue that no error throw when clear pages, get page ranges and upload pages with invalid page range. +## 2020.11 Version 3.11.0-table-alpha.1 + +- First Alpha version of Azurite V3 Table. + ## 2020.10 Version 3.9.0 - Bump up Azure Storage service API version to 2020-02-10. From b188272ed79f711f40fbc6f39d3defb8ecc1ec19 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Tue, 6 Apr 2021 22:17:47 +0800 Subject: [PATCH 38/57] Add missing request/response body logs for batch (#742) --- package-lock.json | 80 +++++++++---------- .../generated/middleware/error.middleware.ts | 11 +-- src/table/generated/utils/serializer.ts | 11 ++- src/table/handlers/TableHandler.ts | 42 ++++++++-- 4 files changed, 84 insertions(+), 60 deletions(-) diff --git a/package-lock.json b/package-lock.json index faac23109..c01a7d9e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.1.tgz", "integrity": "sha512-wP2Jw6uPp8DEDy0n4KNidvwzDjyVV2xnycEIq7nPzj1rHyb/r+t3OPeNT1INZePP2wy5ZqlwyuyOMTi0ePyY1A==", - "dev": true, "requires": { "tslib": "^1.9.3" } @@ -154,18 +153,36 @@ "integrity": "sha512-l7z0DPCi2Hp88w12JhDTtx5d0Y3+vhfE7JKJb9O7sEz71Cwp053N8piTtTnnk/tUor9oZHgEKi/p3tQQmLPjvA==" }, "@azure/ms-rest-js": { - "version": "1.8.13", - "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-1.8.13.tgz", - "integrity": "sha512-jAa6Y2XrvwbEqkaEXDHK+ReNo0WnCPS+LgQ1dRAJUUNxK4CghF5u+SXsVtPENritilVE7FVteqsLOtlhTk+haA==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-1.11.2.tgz", + "integrity": "sha512-2AyQ1IKmLGKW7DU3/x3TsTBzZLcbC9YRI+yuDPuXAQrv3zar340K9wsxU413kHFIDjkWNCo9T0w5VtwcyWxhbQ==", "requires": { - "@types/tunnel": "0.0.0", - "axios": "^0.19.0", + "@azure/core-auth": "^1.1.4", + "axios": "^0.21.1", "form-data": "^2.3.2", "tough-cookie": "^2.4.3", "tslib": "^1.9.2", "tunnel": "0.0.6", "uuid": "^3.2.1", "xml2js": "^0.4.19" + }, + "dependencies": { + "@azure/core-auth": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.3.0.tgz", + "integrity": "sha512-kSDSZBL6c0CYdhb+7KuutnKGf2geeT+bCJAgccB0DD7wmNJSsQPcF7TcuoZX83B7VK4tLz/u+8sOO/CnCsYp8A==", + "requires": { + "@azure/abort-controller": "^1.0.0", + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" + } + } + } } }, "@azure/ms-rest-nodeauth": { @@ -587,21 +604,6 @@ "@types/mime": "*" } }, - "@types/tunnel": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.0.tgz", - "integrity": "sha512-FGDp0iBRiBdPjOgjJmn1NH0KDLN+Z8fRmo+9J7XGBhubq1DPrGrbmG4UTlGzrpbCpesMqD0sWkzi27EYkOMHyg==", - "requires": { - "@types/node": "*" - }, - "dependencies": { - "@types/node": { - "version": "12.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", - "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==" - } - } - }, "@types/uri-templates": { "version": "0.1.30", "resolved": "https://registry.npmjs.org/@types/uri-templates/-/uri-templates-0.1.30.tgz", @@ -848,12 +850,11 @@ "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" }, "axios": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz", - "integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" + "follow-redirects": "^1.10.0" } }, "azure-devops-node-api": { @@ -2527,6 +2528,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -3184,12 +3186,9 @@ "dev": true }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - } + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" }, "for-in": { "version": "1.0.2", @@ -3748,11 +3747,6 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, - "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==" - }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -6768,9 +6762,9 @@ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, "xmldom": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.3.0.tgz", - "integrity": "sha512-z9s6k3wxE+aZHgXYxSTpGDo7BYOUfJsIRyoZiX6HTjwpwfS2wpQBQKa2fD+ShLyPkqDYo5ud7KitmLZ2Cd6r0g==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz", + "integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==" }, "xpath.js": { "version": "1.1.0", @@ -6778,9 +6772,9 @@ "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ==" }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", "dev": true }, "yallist": { diff --git a/src/table/generated/middleware/error.middleware.ts b/src/table/generated/middleware/error.middleware.ts index e923e0c65..696788b04 100644 --- a/src/table/generated/middleware/error.middleware.ts +++ b/src/table/generated/middleware/error.middleware.ts @@ -48,14 +48,12 @@ export default function errorMiddleware( ); logger.error( - `ErrorMiddleware: ErrorName=${err.name} ErrorMessage=${ - err.message - } ErrorHTTPStatusCode=${err.statusCode} ErrorHTTPStatusMessage=${ - err.statusMessage + `ErrorMiddleware: ErrorName=${err.name} ErrorMessage=${JSON.stringify(err.message) + } ErrorHTTPStatusCode=${err.statusCode} ErrorHTTPStatusMessage=${JSON.stringify(err.statusMessage) } ErrorHTTPHeaders=${JSON.stringify( err.headers )} ErrorHTTPBody=${JSON.stringify(err.body)} ErrorStack=${JSON.stringify( - err.stack + JSON.stringify(err.stack) )}`, context.contextID ); @@ -110,8 +108,7 @@ export default function errorMiddleware( context.contextID ); logger.error( - `ErrorMiddleware: ErrorName=${err.name} ErrorMessage=${ - err.message + `ErrorMiddleware: ErrorName=${err.name} ErrorMessage=${err.message } ErrorStack=${JSON.stringify(err.stack)}`, context.contextID ); diff --git a/src/table/generated/utils/serializer.ts b/src/table/generated/utils/serializer.ts index 267659fa5..4b68f5eaa 100644 --- a/src/table/generated/utils/serializer.ts +++ b/src/table/generated/utils/serializer.ts @@ -11,8 +11,8 @@ export declare type ParameterPath = | string | string[] | { - [propertyName: string]: ParameterPath; - }; + [propertyName: string]: ParameterPath; + }; export async function deserialize( context: Context, @@ -69,7 +69,7 @@ export async function deserialize( const headerCollectionPrefix: | string | undefined = (headerParameter.mapper as msRest.DictionaryMapper) - .headerCollectionPrefix; + .headerCollectionPrefix; if (headerCollectionPrefix) { const dictionary: any = {}; const headers = req.getHeaders(); @@ -369,9 +369,12 @@ export async function serialize( ) { logger.info(`Serializer: Start returning stream body.`, context.contextID); - await new Promise((resolve, reject) => { + + + await new Promise((resolve, reject) => { (handlerResponse.body as NodeJS.ReadableStream) .on("error", reject) + .on("end", resolve) .pipe(res.getBodyStream()) .on("error", reject) .on("close", resolve); diff --git a/src/table/handlers/TableHandler.ts b/src/table/handlers/TableHandler.ts index e2306abd8..b3d3a5cb3 100644 --- a/src/table/handlers/TableHandler.ts +++ b/src/table/handlers/TableHandler.ts @@ -237,9 +237,14 @@ export default class TableHandler extends BaseHandler implements ITableHandler { // } // response.body = new BufferStream(Buffer.from(JSON.stringify(body))); - response.body = new BufferStream( - Buffer.from(nomarlizedEntity.toResponseString(accept, body)) + const rawResponse = nomarlizedEntity.toResponseString(accept, body); + this.logger.debug( + `TableHandler:insertEntity() Raw response string is ${JSON.stringify( + rawResponse + )}`, + context.contextID ); + response.body = new BufferStream(Buffer.from(rawResponse)); } this.updateResponseAccept(tableContext, accept); @@ -528,7 +533,9 @@ export default class TableHandler extends BaseHandler implements ITableHandler { response.body = new BufferStream(Buffer.from(body)); this.logger.debug( - `QueryEntities response body: ${body}`, + `TableHandler:queryEntities() Raw response string is ${JSON.stringify( + body + )}`, context.contextID ); @@ -606,8 +613,18 @@ export default class TableHandler extends BaseHandler implements ITableHandler { } const nomarlizedEntity = new NormalizedEntity(entity); - response.body = new BufferStream( - Buffer.from(nomarlizedEntity.toResponseString(accept, body, selectSet)) + const rawResponse = nomarlizedEntity.toResponseString( + accept, + body, + selectSet + ); + response.body = new BufferStream(Buffer.from(rawResponse)); + + this.logger.debug( + `TableHandler:queryEntities() Raw response string is ${JSON.stringify( + rawResponse + )}`, + context.contextID ); this.updateResponseAccept(tableContext, accept); @@ -680,8 +697,21 @@ export default class TableHandler extends BaseHandler implements ITableHandler { ?.replace("batch", "batchresponse"); const tableBatchManager = new TableBatchOrchestrator(tableCtx, this); + const requestBody = await TableBatchUtils.StreamToString(body); + this.logger.debug( + `TableHandler:batch() Raw request string is ${JSON.stringify( + requestBody + )}`, + context.contextID + ); + const response = await tableBatchManager.processBatchRequestAndSerializeResponse( - await TableBatchUtils.StreamToString(body) + requestBody + ); + + this.logger.debug( + `TableHandler:batch() Raw response string is ${JSON.stringify(response)}`, + context.contextID ); // need to convert response to NodeJS.ReadableStream From 948e5eb7efc8f76182d4ad6e0e248583d8a9886e Mon Sep 17 00:00:00 2001 From: Wei Wei Date: Wed, 7 Apr 2021 15:42:33 +0800 Subject: [PATCH 39/57] Fix table etag format to be aligned with server, by escape encode ':' in it (#744) --- ChangeLog.md | 1 + src/common/utils/utils.ts | 6 +++++- tests/table/apis/table.entity.test.ts | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index a3ec75e5c..da366b1fa 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -7,6 +7,7 @@ Table: - Allow empty RowKey in an entity. +- Fix etag format to be aligned with Azure server. ## 2021.2 Version 3.11.0 diff --git a/src/common/utils/utils.ts b/src/common/utils/utils.ts index 8d0ef4e8a..43ec0a3ac 100644 --- a/src/common/utils/utils.ts +++ b/src/common/utils/utils.ts @@ -62,7 +62,11 @@ export function newEtag(): string { export function newTableEntityEtag(startTime: Date): string { // Etag as returned by Table Storage should match W/"datetime''" - return "W/\"datetime'" + truncatedISO8061Date(startTime, true) + "'\""; + return ( + "W/\"datetime'" + + encodeURIComponent(truncatedISO8061Date(startTime, true)) + + "'\"" + ); } /** diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 336f49483..56b71eda3 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -107,7 +107,7 @@ describe("table Entity APIs test", () => { assert.equal(response.statusCode, 201); assert.ok( response.headers?.etag.match( - "W/\"datetime'\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{7}Z'\"" + "W/\"datetime'\\d{4}-\\d{2}-\\d{2}T\\d{2}%3A\\d{2}%3A\\d{2}.\\d{7}Z'\"" ) ); done(); @@ -127,7 +127,7 @@ describe("table Entity APIs test", () => { assert.equal(response.statusCode, 201); assert.ok( response.headers?.etag.match( - "W/\"datetime'\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}.\\d{7}Z'\"" + "W/\"datetime'\\d{4}-\\d{2}-\\d{2}T\\d{2}%3A\\d{2}%3A\\d{2}.\\d{7}Z'\"" ) ); done(); From 17e3c2a64b20891e7cd85ce252ec57a1e2740045 Mon Sep 17 00:00:00 2001 From: Wei Wei Date: Thu, 8 Apr 2021 17:57:29 +0800 Subject: [PATCH 40/57] Fix issue #746 and #748 (#751) --- ChangeLog.md | 2 ++ src/table/entity/EdmDateTime.ts | 10 +++++- src/table/errors/StorageErrorFactory.ts | 11 ++++++ .../persistence/LokiTableMetadataStore.ts | 2 +- tests/table/apis/table.entity.test.ts | 36 +++++++++++++++++++ tests/table/apis/table.test.ts | 2 +- 6 files changed, 60 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index da366b1fa..4d8287c12 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -8,6 +8,8 @@ Table: - Allow empty RowKey in an entity. - Fix etag format to be aligned with Azure server. +- Fix delete none exist table error code and error message, to be aligned with Azure server. +- Convert entity properties with type "Edm.DateTime" to UTC time, to be aligned with Azure server. ## 2021.2 Version 3.11.0 diff --git a/src/table/entity/EdmDateTime.ts b/src/table/entity/EdmDateTime.ts index 6cc2650f0..feb1c60e1 100644 --- a/src/table/entity/EdmDateTime.ts +++ b/src/table/entity/EdmDateTime.ts @@ -16,7 +16,15 @@ export class EdmDateTime implements IEdmType { public typedValue: string; public constructor(public value: any) { - this.typedValue = EdmDateTime.validate(value); + // Azure Server will take time string like "2012-01-02T23:00:00" as UTC time, so Azurite need be aligned by adding suffix "Z" + const utcTimeString = value + "Z"; + const utcTime: Date = new Date(value + "Z"); + if (!isNaN(utcTime.getDay())) { + // When add suffix "Z" is still a validate date string, use the string with suffix "Z"; else use original string + this.typedValue = utcTimeString; + } else { + this.typedValue = EdmDateTime.validate(value); + } } public toJsonPropertyValuePair(name: string): [string, string] { diff --git a/src/table/errors/StorageErrorFactory.ts b/src/table/errors/StorageErrorFactory.ts index 060b6f50c..b2d25a702 100644 --- a/src/table/errors/StorageErrorFactory.ts +++ b/src/table/errors/StorageErrorFactory.ts @@ -234,6 +234,17 @@ export default class StorageErrorFactory { ); } + public static ResourceNotFound(context: Context): StorageError { + return new StorageError( + 404, + "ResourceNotFound", + "The specified resource does not exist.", + context.contextID || defaultID, + undefined, + context + ); + } + public static getEntityNotFound(context: Context): StorageError { return new StorageError( 404, diff --git a/src/table/persistence/LokiTableMetadataStore.ts b/src/table/persistence/LokiTableMetadataStore.ts index 0f59560c9..73a20120f 100644 --- a/src/table/persistence/LokiTableMetadataStore.ts +++ b/src/table/persistence/LokiTableMetadataStore.ts @@ -132,7 +132,7 @@ export default class LokiTableMetadataStore implements ITableMetadataStore { if (doc) { coll.remove(doc); } else { - throw StorageErrorFactory.getTableNotFound(context); + throw StorageErrorFactory.ResourceNotFound(context); } const tableCollectionName = this.getTableCollectionName(account, table); diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 56b71eda3..2cd02e341 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -114,6 +114,42 @@ describe("table Entity APIs test", () => { }); }); + // Insert entity property with type "Edm.DateTime", server will convert to UTC time + it("Insert new Entity property with type Edm.DateTime will convert to UTC, @loki", (done) => { + const timeValue = "2012-01-02T23:00:00"; + const entity = { + PartitionKey: "part1", + RowKey: "utctest", + myValue: timeValue, + "myValue@odata.type": "Edm.DateTime" + }; + + tableService.insertEntity( + tableName, + entity, + (insertError, insertResult, insertResponse) => { + if (!insertError) { + tableService.retrieveEntity( + tableName, + "part1", + "utctest", + (error, result) => { + const entity: TestEntity = result; + assert.strictEqual( + entity.myValue._.toString(), + new Date(timeValue + "Z").toString() + ); + done(); + } + ); + } else { + assert.ifError(insertError); + done(); + } + } + ); + }); + // Simple test in here until we have the full set checked in, as we need // a starting point for delete and query entity APIs it("Should insert new Entity with empty RowKey, @loki", (done) => { diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index 408536062..243f093d9 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -251,7 +251,7 @@ describe("table APIs test", () => { tableService.deleteTable(tableToDelete, (error, result) => { assert.equal(result.statusCode, 404); // no body expected, we expect 404 const storageError = error as any; - assert.equal(storageError.code, "TableNotFound"); + assert.equal(storageError.code, "ResourceNotFound"); done(); }); }); From 1fb5280e8308f420410b5b92445e7cd94285319e Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Wed, 14 Apr 2021 16:20:54 +0200 Subject: [PATCH 41/57] Update to Table Batch API to address complex row and partition keys (#752) * fixed function to parse partition key and row key, added test to test for cases relating to logic apps and durable function style keys * updated regex to cover case for durable functions and added tests * updated changelog * removed URL encoded quotes on Location and DataServiceId to fix #738 * added check for etag escaping in batch requests * tidied up the url parsing for row & partition key using decoded URL --- ChangeLog.md | 2 + src/table/batch/TableBatchOrchestrator.ts | 26 +-- src/table/batch/TableBatchSerialization.ts | 17 +- tests/table/apis/table.entity.test.ts | 233 +++++++++++++++++++++ 4 files changed, 252 insertions(+), 26 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 4d8287c12..a707f63f2 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,6 +10,8 @@ Table: - Fix etag format to be aligned with Azure server. - Fix delete none exist table error code and error message, to be aligned with Azure server. - Convert entity properties with type "Edm.DateTime" to UTC time, to be aligned with Azure server. +- Support Batch API +- Allow complex RowKey and PartitionKey in batch API ## 2021.2 Version 3.11.0 diff --git a/src/table/batch/TableBatchOrchestrator.ts b/src/table/batch/TableBatchOrchestrator.ts index 747f7011c..b029ae71b 100644 --- a/src/table/batch/TableBatchOrchestrator.ts +++ b/src/table/batch/TableBatchOrchestrator.ts @@ -246,26 +246,14 @@ export default class TableBatchOrchestrator { let partitionKey: string; let rowKey: string; - const url = request.getUrl(); - const partKeyMatch = url.match(/(PartitionKey=)(%27)?'?(\w+)/gi); + const url = decodeURI(request.getUrl()); + // URL should always be URL encoded + const partKeyMatch = url.match(/(?<=PartitionKey=')(.+)(?=',)/gi); partitionKey = partKeyMatch ? partKeyMatch[0] : ""; - const rowKeyMatch = url.match(/(RowKey=)(%27)?'?(\w+)/gi); + const rowKeyMatch = url.match(/(?<=RowKey=')(.+)(?='\))/gi); rowKey = rowKeyMatch ? rowKeyMatch[0] : ""; - if (partitionKey !== "" || rowKey !== "") { - // we need to filter out the delimeter (if URL encoded) - const urlencodedMatch = partitionKey.match(/%/); - let matchStringLength = 14; - if (urlencodedMatch) { - matchStringLength += 2; - } - partitionKey = partitionKey.substring(matchStringLength); - matchStringLength = 8; - if (urlencodedMatch) { - matchStringLength += 2; - } - rowKey = rowKey.substring(matchStringLength); - } else { + if (partitionKey === "" || rowKey === "") { // row key not in URL, must be in body const body = request.getBody(); if (body !== "") { @@ -273,6 +261,10 @@ export default class TableBatchOrchestrator { partitionKey = jsonBody.PartitionKey; rowKey = jsonBody.RowKey; } + } else { + // keys can have more complex values which are URI encoded + partitionKey = decodeURIComponent(partitionKey); + rowKey = decodeURIComponent(rowKey); } return { partitionKey, rowKey }; } diff --git a/src/table/batch/TableBatchSerialization.ts b/src/table/batch/TableBatchSerialization.ts index ca78c3e2e..2b4706ac8 100644 --- a/src/table/batch/TableBatchSerialization.ts +++ b/src/table/batch/TableBatchSerialization.ts @@ -183,8 +183,7 @@ export class TableBatchSerialization extends BatchSerialization { this.SerializeEntityPath(serializedResponses, request); if (null !== response.eTag && undefined !== response.eTag) { - // prettier-ignore - serializedResponses += "ETag: " + response.eTag.replace(":","%3A"); + serializedResponses += "ETag: " + response.eTag; } return serializedResponses; } @@ -258,7 +257,7 @@ export class TableBatchSerialization extends BatchSerialization { ); if (null !== response.eTag && undefined !== response.eTag) { - serializedResponses += "ETag: " + response.eTag.replace(":", "%3A"); + serializedResponses += "ETag: " + response.eTag; } return serializedResponses; } @@ -317,7 +316,7 @@ export class TableBatchSerialization extends BatchSerialization { ); if (null !== response.eTag && undefined !== response.eTag) { - serializedResponses += "ETag: " + response.eTag.replace(":", "%3A"); + serializedResponses += "ETag: " + response.eTag; } return serializedResponses; } @@ -354,7 +353,7 @@ export class TableBatchSerialization extends BatchSerialization { serializedResponses = this.AddNoSniffNoCache(serializedResponses); if (response.eTag) { - serializedResponses += "ETag: " + response.eTag.replace(":", "%3A"); + serializedResponses += "ETag: " + response.eTag; } serializedResponses += "\r\n"; @@ -544,12 +543,12 @@ export class TableBatchSerialization extends BatchSerialization { const trimmedUrl: string = request .getUrl() .substring(0, parenthesesPosition); - let entityPath = trimmedUrl + "(PartitionKey=%27"; + let entityPath = trimmedUrl + "(PartitionKey='"; entityPath += request.params.tableEntityProperties!.PartitionKey; - entityPath += "%27,"; - entityPath += "RowKey=%27"; + entityPath += "',"; + entityPath += "RowKey='"; entityPath += request.params.tableEntityProperties!.RowKey; - entityPath += "%27)\r\n"; + entityPath += "')\r\n"; return entityPath; } diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index 2cd02e341..b4f2be7a3 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -1016,4 +1016,237 @@ describe("table Entity APIs test", () => { ); }); }); + + // this covers the following issues + // https://github.com/Azure/Azurite/issues/750 + // https://github.com/Azure/Azurite/issues/733 + // https://github.com/Azure/Azurite/issues/745 + it("Operates on batch items with complex row keys, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const insertEntity1 = createBasicEntityForTest(); + insertEntity1.RowKey._ = "8b0a63c8-9542-49d8-9dd2-d7af9fa8790f_0B"; + const insertEntity2 = createBasicEntityForTest(); + insertEntity2.RowKey._ = "8b0a63c8-9542-49d8-9dd2-d7af9fa8790f_0C"; + const insertEntity3 = createBasicEntityForTest(); + insertEntity3.RowKey._ = "8b0a63c8-9542-49d8-9dd2-d7af9fa8790f_0D"; + const insertEntity4 = createBasicEntityForTest(); + insertEntity4.RowKey._ = "8b0a63c8-9542-49d8-9dd2-d7af9fa8790f_0E"; + + tableService.insertEntity(tableName, insertEntity1, () => { + tableService.insertEntity(tableName, insertEntity2, () => { + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.insertEntity(insertEntity3, { echoContent: true }); + entityBatch.insertEntity(insertEntity4, {}); + entityBatch.deleteEntity(insertEntity1); + entityBatch.deleteEntity(insertEntity2); + tableService.executeBatch( + tableName, + entityBatch, + (batchError, batchResult, batchResponse) => { + if (batchError) { + assert.ifError(batchError); + done(); + } else { + assert.equal(batchResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + insertEntity3.PartitionKey._, + insertEntity3.RowKey._, + (error: any, result, response) => { + assert.strictEqual( + response.statusCode, + 200, + "We did not find the 3rd entity!" + ); + tableService.retrieveEntity( + tableName, + insertEntity4.PartitionKey._, + insertEntity4.RowKey._, + (error2: any, result2, response2) => { + assert.strictEqual( + response2.statusCode, + 200, + "We did not find the 4th entity!" + ); + tableService.retrieveEntity( + tableName, + insertEntity1.PartitionKey._, + insertEntity1.RowKey._, + (error3: any, result3, response3) => { + assert.strictEqual( + response3.statusCode, + 404, + "We did not delete the 1st entity!" + ); + tableService.retrieveEntity( + tableName, + insertEntity2.PartitionKey._, + insertEntity2.RowKey._, + (error4: any, result4, response4) => { + assert.strictEqual( + response4.statusCode, + 404, + "We did not delete the 2nd entity!" + ); + done(); + } + ); + } + ); + } + ); + } + ); + } + } + ); + }); + }); + }); + + // this covers https://github.com/Azure/Azurite/issues/741 + it("Operates on batch items with complex partition keys, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const insertEntity1 = createBasicEntityForTest(); + insertEntity1.PartitionKey._ = + "@DurableTask.AzureStorage.Tests.AzureStorageScenarioTests+Orchestrations+AutoStartOrchestration+Responder"; + const insertEntity2 = createBasicEntityForTest(); + insertEntity2.PartitionKey._ = + "@DurableTask.AzureStorage.Tests.AzureStorageScenarioTests+Orchestrations+AutoStartOrchestration+Responder"; + const insertEntity3 = createBasicEntityForTest(); + insertEntity3.PartitionKey._ = + "@DurableTask.AzureStorage.Tests.AzureStorageScenarioTests+Orchestrations+AutoStartOrchestration+Responder"; + const insertEntity4 = createBasicEntityForTest(); + insertEntity4.PartitionKey._ = + "@DurableTask.AzureStorage.Tests.AzureStorageScenarioTests+Orchestrations+AutoStartOrchestration+Responder"; + + tableService.insertEntity(tableName, insertEntity1, () => { + tableService.insertEntity(tableName, insertEntity2, () => { + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.insertEntity(insertEntity3, { echoContent: true }); + entityBatch.insertEntity(insertEntity4, {}); + entityBatch.deleteEntity(insertEntity1); + entityBatch.deleteEntity(insertEntity2); + tableService.executeBatch( + tableName, + entityBatch, + (batchError, batchResult, batchResponse) => { + if (batchError) { + assert.ifError(batchError); + done(); + } else { + assert.equal(batchResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + insertEntity3.PartitionKey._, + insertEntity3.RowKey._, + (error: any, result, response) => { + assert.strictEqual( + response.statusCode, + 200, + "We did not find the 3rd entity!" + ); + tableService.retrieveEntity( + tableName, + insertEntity4.PartitionKey._, + insertEntity4.RowKey._, + (error2: any, result2, response2) => { + assert.strictEqual( + response2.statusCode, + 200, + "We did not find the 4th entity!" + ); + tableService.retrieveEntity( + tableName, + insertEntity1.PartitionKey._, + insertEntity1.RowKey._, + (error3: any, result3, response3) => { + assert.strictEqual( + response3.statusCode, + 404, + "We did not delete the 1st entity!" + ); + tableService.retrieveEntity( + tableName, + insertEntity2.PartitionKey._, + insertEntity2.RowKey._, + (error4: any, result4, response4) => { + assert.strictEqual( + response4.statusCode, + 404, + "We did not delete the 2nd entity!" + ); + done(); + } + ); + } + ); + } + ); + } + ); + } + } + ); + }); + }); + }); + + it("Ensure Valid Etag format from Batch, @loki", (done) => { + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + const batchEntity1 = createBasicEntityForTest(); + + const entityBatch: Azure.TableBatch = new Azure.TableBatch(); + entityBatch.addOperation("INSERT", batchEntity1, { echoContent: true }); + batchEntity1.myValue._ = "value2"; + entityBatch.mergeEntity(batchEntity1); + + tableService.executeBatch( + tableName, + entityBatch, + (updateError, updateResult, updateResponse) => { + if (updateError) { + assert.ifError(updateError); + done(); + } else { + assert.equal(updateResponse.statusCode, 202); + tableService.retrieveEntity( + tableName, + batchEntity1.PartitionKey._, + batchEntity1.RowKey._, + (error, result, response) => { + if (error) { + assert.ifError(error); + } else if (result) { + const entity: TestEntity = result; + assert.equal(entity.myValue._, batchEntity1.myValue._); + + if (response !== null) { + const body: any = response?.body; + assert.notStrictEqual(body, null, "response empty"); + if (body != null) { + assert.strictEqual( + body["odata.etag"].match(/(%3A)/).length, + 2, + "did not find the expected number of escaped sequences" + ); + } + } + } + done(); + } + ); + } + } + ); + }); }); From 2cf4deae207c070473a7b0be2bfe47c81a8df5b2 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Thu, 15 Apr 2021 16:36:04 +0200 Subject: [PATCH 42/57] added test for @azure/data-tables (#753) --- package-lock.json | 270 ++++++++++++++++++ package.json | 1 + src/table/batch/TableBatchOrchestrator.ts | 1 - .../table.entity.tests.azure.data-tables.ts | 104 +++++++ 4 files changed, 375 insertions(+), 1 deletion(-) create mode 100644 tests/table/apis/table.entity.tests.azure.data-tables.ts diff --git a/package-lock.json b/package-lock.json index c01a7d9e9..6fb4170a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,55 @@ } } }, + "@azure/core-client": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.1.0.tgz", + "integrity": "sha512-IYnzroWd6QmxTGTKn9vA00zZ8KQ1ox0BqMEEiiaJ2RY3fvCHWMQSaf4OSi0al7QfwWd+XPEN2yzGSgR56yPnlw==", + "dev": true, + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-asynciterator-polyfill": "^1.0.0", + "@azure/core-auth": "^1.3.0", + "@azure/core-rest-pipeline": "^1.0.0", + "@azure/core-tracing": "1.0.0-preview.11", + "tslib": "^2.0.0" + }, + "dependencies": { + "@azure/core-auth": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.3.0.tgz", + "integrity": "sha512-kSDSZBL6c0CYdhb+7KuutnKGf2geeT+bCJAgccB0DD7wmNJSsQPcF7TcuoZX83B7VK4tLz/u+8sOO/CnCsYp8A==", + "dev": true, + "requires": { + "@azure/abort-controller": "^1.0.0", + "tslib": "^2.0.0" + } + }, + "@azure/core-tracing": { + "version": "1.0.0-preview.11", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.11.tgz", + "integrity": "sha512-frF0pJc9HTmKncVokhBxCqipjbql02DThQ1ZJ9wLi7SDMLdPAFyDI5xZNzX5guLz+/DtPkY+SGK2li9FIXqshQ==", + "dev": true, + "requires": { + "@opencensus/web-types": "0.0.7", + "@opentelemetry/api": "1.0.0-rc.0", + "tslib": "^2.0.0" + } + }, + "@opentelemetry/api": { + "version": "1.0.0-rc.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.0-rc.0.tgz", + "integrity": "sha512-iXKByCMfrlO5S6Oh97BuM56tM2cIBB0XsL/vWF/AtJrJEKx4MC/Xdu0xDsGXMGcNWpqF7ujMsjjnp0+UHBwnDQ==", + "dev": true + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + } + } + }, "@azure/core-http": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-1.1.4.tgz", @@ -127,6 +176,75 @@ "@azure/core-asynciterator-polyfill": "^1.0.0" } }, + "@azure/core-rest-pipeline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.0.3.tgz", + "integrity": "sha512-GbfBQHF83RQI+LVISh8RLKpPeyufFsu6FhwB0U1inN7BWo8GuE23s0vc/D4gd5AWww7orQ20Q3zMzW5FKFs4MQ==", + "dev": true, + "requires": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.3.0", + "@azure/core-tracing": "1.0.0-preview.11", + "@azure/logger": "^1.0.0", + "form-data": "^3.0.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "tslib": "^2.0.0", + "uuid": "^8.3.0" + }, + "dependencies": { + "@azure/core-auth": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.3.0.tgz", + "integrity": "sha512-kSDSZBL6c0CYdhb+7KuutnKGf2geeT+bCJAgccB0DD7wmNJSsQPcF7TcuoZX83B7VK4tLz/u+8sOO/CnCsYp8A==", + "dev": true, + "requires": { + "@azure/abort-controller": "^1.0.0", + "tslib": "^2.0.0" + } + }, + "@azure/core-tracing": { + "version": "1.0.0-preview.11", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.11.tgz", + "integrity": "sha512-frF0pJc9HTmKncVokhBxCqipjbql02DThQ1ZJ9wLi7SDMLdPAFyDI5xZNzX5guLz+/DtPkY+SGK2li9FIXqshQ==", + "dev": true, + "requires": { + "@opencensus/web-types": "0.0.7", + "@opentelemetry/api": "1.0.0-rc.0", + "tslib": "^2.0.0" + } + }, + "@opentelemetry/api": { + "version": "1.0.0-rc.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.0-rc.0.tgz", + "integrity": "sha512-iXKByCMfrlO5S6Oh97BuM56tM2cIBB0XsL/vWF/AtJrJEKx4MC/Xdu0xDsGXMGcNWpqF7ujMsjjnp0+UHBwnDQ==", + "dev": true + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } + } + }, "@azure/core-tracing": { "version": "1.0.0-preview.8", "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.8.tgz", @@ -138,6 +256,71 @@ "tslib": "^1.10.0" } }, + "@azure/core-xml": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@azure/core-xml/-/core-xml-1.0.0-beta.1.tgz", + "integrity": "sha512-7d2w0yd8pb1c9aj87JV/1ntOp+sCMcJ9QoGDxs6/7BLDh8Gb6kd2h3n+9JYhcLZO8wdHZb4d4GZgmRIwaAU72w==", + "dev": true, + "requires": { + "tslib": "^2.0.0", + "xml2js": "^0.4.19" + }, + "dependencies": { + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + } + } + }, + "@azure/data-tables": { + "version": "12.0.0-beta.2", + "resolved": "https://registry.npmjs.org/@azure/data-tables/-/data-tables-12.0.0-beta.2.tgz", + "integrity": "sha512-0bxVa9pTyeKjuLOMx+PGGfEOeY+JH1e1j3GrB7PrrFE8H3yB0RhqCZi5CSqojidgWuhYNK0nh5RG68v3WqQgcg==", + "dev": true, + "requires": { + "@azure/core-client": "^1.0.0", + "@azure/core-paging": "^1.1.1", + "@azure/core-rest-pipeline": "^1.0.0", + "@azure/core-tracing": "1.0.0-preview.11", + "@azure/core-xml": "1.0.0-beta.1", + "@azure/logger": "^1.0.0", + "tslib": "^2.0.0", + "uuid": "^8.3.0" + }, + "dependencies": { + "@azure/core-tracing": { + "version": "1.0.0-preview.11", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.11.tgz", + "integrity": "sha512-frF0pJc9HTmKncVokhBxCqipjbql02DThQ1ZJ9wLi7SDMLdPAFyDI5xZNzX5guLz+/DtPkY+SGK2li9FIXqshQ==", + "dev": true, + "requires": { + "@opencensus/web-types": "0.0.7", + "@opentelemetry/api": "1.0.0-rc.0", + "tslib": "^2.0.0" + } + }, + "@opentelemetry/api": { + "version": "1.0.0-rc.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.0-rc.0.tgz", + "integrity": "sha512-iXKByCMfrlO5S6Oh97BuM56tM2cIBB0XsL/vWF/AtJrJEKx4MC/Xdu0xDsGXMGcNWpqF7ujMsjjnp0+UHBwnDQ==", + "dev": true + }, + "tslib": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", + "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } + } + }, "@azure/logger": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.0.tgz", @@ -423,6 +606,12 @@ "any-observable": "^0.3.0" } }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, "@types/args": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/args/-/args-3.0.0.tgz", @@ -672,6 +861,32 @@ } } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "ajv": { "version": "6.12.5", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", @@ -3515,6 +3730,34 @@ "toidentifier": "1.0.0" } }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -3525,6 +3768,33 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "husky": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.5.tgz", diff --git a/package.json b/package.json index effe42bd3..74f7cad2b 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "xml2js": "^0.4.19" }, "devDependencies": { + "@azure/data-tables": "^12.0.0-beta.2", "@azure/storage-blob": "^12.1.2", "@azure/storage-queue": "^12.0.5", "@types/args": "^3.0.0", diff --git a/src/table/batch/TableBatchOrchestrator.ts b/src/table/batch/TableBatchOrchestrator.ts index b029ae71b..f0b451cfa 100644 --- a/src/table/batch/TableBatchOrchestrator.ts +++ b/src/table/batch/TableBatchOrchestrator.ts @@ -247,7 +247,6 @@ export default class TableBatchOrchestrator { let rowKey: string; const url = decodeURI(request.getUrl()); - // URL should always be URL encoded const partKeyMatch = url.match(/(?<=PartitionKey=')(.+)(?=',)/gi); partitionKey = partKeyMatch ? partKeyMatch[0] : ""; const rowKeyMatch = url.match(/(?<=RowKey=')(.+)(?='\))/gi); diff --git a/tests/table/apis/table.entity.tests.azure.data-tables.ts b/tests/table/apis/table.entity.tests.azure.data-tables.ts new file mode 100644 index 000000000..677b1f8c0 --- /dev/null +++ b/tests/table/apis/table.entity.tests.azure.data-tables.ts @@ -0,0 +1,104 @@ +// Tests in this file are using @azure/data-tables + +import * as assert from "assert"; +import { TableClient, TablesSharedKeyCredential } from "@azure/data-tables"; +import { configLogger } from "../../../src/common/Logger"; +import TableConfiguration from "../../../src/table/TableConfiguration"; +import TableServer from "../../../src/table/TableServer"; +import { + EMULATOR_ACCOUNT_KEY, + EMULATOR_ACCOUNT_NAME, + getUniqueName +} from "../../testutils"; + +// Set true to enable debug log +configLogger(false); +const partitionKeyForDataTablesTests: string = "datatables-tests"; +/** + * Creates an entity for tests, with a randomized row key, + * to avoid conflicts on inserts. + * + * @return {*} {TestEntity} + */ +function createBasicEntityForTest(): AzureDataTablesTestEntity { + return new AzureDataTablesTestEntity( + partitionKeyForDataTablesTests, + getUniqueName("row"), + "value1" + ); +} + +class AzureDataTablesTestEntity { + public partitionKey: string; + public rowKey: string; + public myValue: string; + constructor(part: string, row: string, value: string) { + this.partitionKey = part; + this.rowKey = row; + this.myValue = value; + } +} + +describe("table Entity APIs test", () => { + // TODO: Create a server factory as tests utils + const protocol = "https"; + const host = "127.0.0.1"; + const port = 11002; + const metadataDbPath = "__tableTestsStorage__"; + const enableDebugLog: boolean = true; + const debugLogPath: string = "g:/debug.log"; + const config = new TableConfiguration( + host, + port, + metadataDbPath, + enableDebugLog, + false, + undefined, + debugLogPath, + false, + true, + "tests/server.cert", + "tests/server.key" + ); + + let server: TableServer; + const accountName = EMULATOR_ACCOUNT_NAME; + const sharedKey = EMULATOR_ACCOUNT_KEY; + const tableName: string = getUniqueName("datatables"); + + const tableClient = new TableClient( + `${protocol}://${host}:${port}/${accountName}`, + tableName, + new TablesSharedKeyCredential(accountName, sharedKey) + ); + + const requestOverride = { headers: {} }; + + before(async () => { + server = new TableServer(config); + await server.start(); + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + }); + + after(async () => { + await server.close(); + }); + + it("Batch API should return row keys in format understood by @azure/data-tables, @loki", async () => { + const testEntities: AzureDataTablesTestEntity[] = [ + createBasicEntityForTest(), + createBasicEntityForTest(), + createBasicEntityForTest() + ]; + + await tableClient.create(); + const batch = tableClient.createBatch(partitionKeyForDataTablesTests); + await batch.createEntities(testEntities); + const result = await batch.submitBatch(); + assert.ok(result.subResponses[0].rowKey); + await tableClient.delete(); + }); +}); From 5dee9b428fd5f74d5254eb700585fc9b60fe2a47 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Sat, 17 Apr 2021 19:58:59 +0200 Subject: [PATCH 43/57] trying to repro logic app issues --- .../apis/table.entity.test.logicapp.entity.ts | 38 ++++++++ .../table.entity.tests.azure.data-tables.ts | 92 ++++++++++++++++++- 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 tests/table/apis/table.entity.test.logicapp.entity.ts diff --git a/tests/table/apis/table.entity.test.logicapp.entity.ts b/tests/table/apis/table.entity.test.logicapp.entity.ts new file mode 100644 index 000000000..6a3f860fe --- /dev/null +++ b/tests/table/apis/table.entity.test.logicapp.entity.ts @@ -0,0 +1,38 @@ +/** + * currently simple object not using odata.edm types, can be extended for repros + * + * @export + * @class LogicAppReproEntity + */ +export default class LogicAppReproEntity { + partitionKey: string = "09CEE"; + rowKey: string = + "EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786980800821"; + sequenceNumber: number = 0; + testString: string = "0"; + Sku: string = + '{"name":"Standard","plan":{"name":"farm0","id":"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0","type":"Microsoft.Web/ServerFarms"}}'; + State: string = "Enabled"; + CreatedTime: string = "2021-04-15T23:09:47.4209193Z"; + ChangedTime: string = "2021-04-15T23:09:47.4214726Z"; + DeletedTime: string = "1970-01-01T00:00:00Z"; + ChangedOperationId: string = "f2503371-15c7-4314-9803-81ea69f1ca72"; + FlowId: string = "5539f65e020b44fca32cf9cbe56e286a"; + SubscriptionId: string = "ea5f528c-f1b8-4658-a5ce-cc574848547b"; + ResourceGroupName: string = "de415c09-29bb-483d-9544-25602c1ff355"; + FlowName: string = "testflow1"; + FlowSequenceId: string = "08585830786980800821"; + ScaleUnit: string = "CU03"; + Location: string = "devfabric"; + RuntimeConfiguration: string = "{}"; + DefinitionCompressed: string = + "jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg=="; + Metadata: string = "F3t9"; + ParametersCompressed: string = "F3t9"; + ConnectionReferences: string = "F3t9"; + WorkflowReferences: string = "F3t9"; + KeyVaultCertificateReferences: string = "F3t9"; + RuntimeContext: string = + "9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ"; + FlowUpdatedTime: string = "2021-04-15T23:09:47.4101988Z"; +} diff --git a/tests/table/apis/table.entity.tests.azure.data-tables.ts b/tests/table/apis/table.entity.tests.azure.data-tables.ts index 677b1f8c0..dbadb7a3e 100644 --- a/tests/table/apis/table.entity.tests.azure.data-tables.ts +++ b/tests/table/apis/table.entity.tests.azure.data-tables.ts @@ -1,6 +1,7 @@ // Tests in this file are using @azure/data-tables import * as assert from "assert"; +import LogicAppReproEntity from "./table.entity.test.logicapp.entity"; import { TableClient, TablesSharedKeyCredential } from "@azure/data-tables"; import { configLogger } from "../../../src/common/Logger"; import TableConfiguration from "../../../src/table/TableConfiguration"; @@ -13,7 +14,7 @@ import { // Set true to enable debug log configLogger(false); -const partitionKeyForDataTablesTests: string = "datatables-tests"; +const partitionKeyForDataTablesTests: string = getUniqueName("datatablestests"); /** * Creates an entity for tests, with a randomized row key, * to avoid conflicts on inserts. @@ -101,4 +102,93 @@ describe("table Entity APIs test", () => { assert.ok(result.subResponses[0].rowKey); await tableClient.delete(); }); + + // https://github.com/Azure/Azurite/issues/754 + it.only("Batch API should correctly process LogicApp style update request sequence", async () => { + await tableClient.create(); + const logicAppReproEntity = new LogicAppReproEntity(); + const insertedEntityHeaders = await tableClient.createEntity< + LogicAppReproEntity + >(logicAppReproEntity); + assert.notStrictEqual(insertedEntityHeaders.etag, undefined); + logicAppReproEntity.sequenceNumber = 1; + logicAppReproEntity.testString = "1"; + const updatedEntityHeaders = await tableClient.updateEntity( + logicAppReproEntity, + "Merge" + ); + assert.notStrictEqual( + updatedEntityHeaders.etag, + insertedEntityHeaders.etag + ); + // make sure that the entity was updated + const updatedEntity = await tableClient.getEntity( + logicAppReproEntity.partitionKey, + logicAppReproEntity.rowKey + ); + assert.strictEqual(updatedEntity.etag, updatedEntityHeaders.etag); + assert.strictEqual(updatedEntity.sequenceNumber, 1); + assert.strictEqual(updatedEntity.testString, "1"); + // simple update works, now test batch updates + // insert 2 update 1 + const batchEntity1 = new LogicAppReproEntity(); + batchEntity1.rowKey = batchEntity1.rowKey + "1"; + const batchEntity2 = new LogicAppReproEntity(); + batchEntity2.rowKey = batchEntity1.rowKey + "2"; + // here we update the original entity created with non batch insert + updatedEntity.testString = "2"; + updatedEntity.sequenceNumber = 2; + + // Batch using replace mode + const batch1 = tableClient.createBatch(batchEntity1.partitionKey); + batch1.createEntity(batchEntity1); + batch1.createEntity(batchEntity2); + batch1.updateEntity(updatedEntity, "Replace"); + + const result = await batch1.submitBatch(); + // batch operations succeeded + assert.strictEqual( + result.subResponses[0].status, + 204, + "error with batchEntity1 create" + ); + assert.strictEqual( + result.subResponses[1].status, + 204, + "error with batchEntity2 create" + ); + assert.strictEqual( + result.subResponses[2].status, + 204, + "error with updatedEntity update" + ); + // we have a new etag from the updated entity + assert.notStrictEqual(result.subResponses[2].etag, updatedEntity.etag); + + const batch2 = tableClient.createBatch(batchEntity1.partitionKey); + batch2.deleteEntity(batchEntity1.partitionKey, batchEntity1.rowKey); + batch2.deleteEntity(batchEntity2.partitionKey, batchEntity2.rowKey); + batch2.deleteEntity(updatedEntity.partitionKey, updatedEntity.rowKey, { + etag: result.subResponses[2].etag + }); + + const result2 = await batch2.submitBatch(); + assert.strictEqual( + result2.subResponses[0].status, + 204, + "error with batchEntity1 delete" + ); + assert.strictEqual( + result2.subResponses[1].status, + 204, + "error with batchEntity2 delete" + ); + assert.strictEqual( + result2.subResponses[2].status, + 204, + "error with updatedEntity delete" + ); + + await tableClient.delete(); + }); }); From dd34946bf811d7056efd82ccfc3e797bb1e4c5ab Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Sat, 17 Apr 2021 22:36:50 +0200 Subject: [PATCH 44/57] removed auth from table middleware to make testing easier with debug log from Logic apps, need toi implement proper option on azurite to turn off auth --- package.json | 1 + src/table/TableRequestListenerFactory.ts | 14 +- .../apis/table.entity.tests.azure.rest.ts | 162 ++++++++++++++++++ 3 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 tests/table/apis/table.entity.tests.azure.rest.ts diff --git a/package.json b/package.json index 74f7cad2b..c555e1f03 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "@types/vscode": "^1.39.0", "@types/xml2js": "^0.4.3", "autorest": "^2.0.4413", + "axios": "^0.21.1", "cross-env": "^6.0.3", "cross-var": "^1.1.0", "husky": "^4.3.5", diff --git a/src/table/TableRequestListenerFactory.ts b/src/table/TableRequestListenerFactory.ts index 0e7c4c340..077e819ee 100644 --- a/src/table/TableRequestListenerFactory.ts +++ b/src/table/TableRequestListenerFactory.ts @@ -75,7 +75,7 @@ export default class TableRequestListenerFactory // TODO: Override Query Table JSON response element value TableQueryResponse.type.modelProperties!.value.xmlElementName = "value"; - + const useAuth = false; const app = express().disable("x-powered-by"); // MiddlewareFactory is a factory to create auto-generated middleware @@ -124,11 +124,13 @@ export default class TableRequestListenerFactory logger ) ]; - app.use( - authenticationMiddlewareFactory.createAuthenticationMiddleware( - authenticators - ) - ); + if (useAuth) { + app.use( + authenticationMiddlewareFactory.createAuthenticationMiddleware( + authenticators + ) + ); + } // Generated, will do basic validation defined in swagger app.use(middlewareFactory.createDeserializerMiddleware()); diff --git a/tests/table/apis/table.entity.tests.azure.rest.ts b/tests/table/apis/table.entity.tests.azure.rest.ts new file mode 100644 index 000000000..457fe4a66 --- /dev/null +++ b/tests/table/apis/table.entity.tests.azure.rest.ts @@ -0,0 +1,162 @@ +// Tests in this file are using raw rest requests, +// as this enables us to test calls which are otherwise not possible +// using the SDKs + +import * as assert from "assert"; +import axios from "axios"; +import { configLogger } from "../../../src/common/Logger"; +import TableConfiguration from "../../../src/table/TableConfiguration"; +import TableServer from "../../../src/table/TableServer"; +import { + EMULATOR_ACCOUNT_KEY, + EMULATOR_ACCOUNT_NAME, + getUniqueName +} from "../../testutils"; + +// Set true to enable debug log +configLogger(false); +// const partitionKeyForDataTablesTests: string = getUniqueName("datatablestests"); +/** + * Creates an entity for tests, with a randomized row key, + * to avoid conflicts on inserts. + * + * @return {*} {TestEntity} + */ +// const testEntity = { +// Address: "Mountain View", +// Age: 23, +// AmountDue: 200.23, +// "CustomerCode@odata.type": "Edm.Guid", +// CustomerCode: "c9da6455-213d-42c9-9a79-3e9149a57833", +// "CustomerSince@odata.type": "Edm.DateTime", +// CustomerSince: "2008-07-10T00:00:00", +// IsActive: true, +// "NumberOfOrders@odata.type": "Edm.Int64", +// NumberOfOrders: "255", +// PartitionKey: partitionKeyForDataTablesTests, +// RowKey: getUniqueName("row") +// }; + +// class AzureDataTablesTestEntity { +// public partitionKey: string; +// public rowKey: string; +// public myValue: string; +// constructor(part: string, row: string, value: string) { +// this.partitionKey = part; +// this.rowKey = row; +// this.myValue = value; +// } +// } + +describe("table Entity APIs test", () => { + // TODO: Create a server factory as tests utils + const protocol = "http"; + const host = "127.0.0.1"; + const port = 11002; + const metadataDbPath = "__tableTestsStorage__"; + const enableDebugLog: boolean = true; + const debugLogPath: string = "g:/debug.log"; + const config = new TableConfiguration( + host, + port, + metadataDbPath, + enableDebugLog, + false, + undefined, + debugLogPath, + false, + true + ); + + let server: TableServer; + const accountName = EMULATOR_ACCOUNT_NAME; + const sharedKey = EMULATOR_ACCOUNT_KEY; + // const tableName: string = getUniqueName("datatables"); + const reproFlowsTableName: string = getUniqueName("flows"); + + const request1RawRequestString: string = `--batch_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: multipart/mixed; boundary=changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\n\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{"PartitionKey":"09CEE","RowKey":"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786980800821","Sku":"{\\"name\\":\\"Standard\\",\\"plan\\":{\\"name\\":\\"farm0\\",\\"id\\":\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\",\\"type\\":\\"Microsoft.Web/ServerFarms\\"}}","State":"Enabled","CreatedTime":"2021-04-15T23:09:47.4209193Z","CreatedTime@odata.type":"Edm.DateTime","ChangedTime":"2021-04-15T23:09:47.4214726Z","ChangedTime@odata.type":"Edm.DateTime","DeletedTime":"1970-01-01T00:00:00Z","DeletedTime@odata.type":"Edm.DateTime","ChangedOperationId":"f2503371-15c7-4314-9803-81ea69f1ca72","FlowId":"5539f65e020b44fca32cf9cbe56e286a","SubscriptionId":"ea5f528c-f1b8-4658-a5ce-cc574848547b","ResourceGroupName":"de415c09-29bb-483d-9544-25602c1ff355","FlowName":"testflow1","FlowSequenceId":"08585830786980800821","ScaleUnit":"CU03","Location":"devfabric","RuntimeConfiguration":"{}","DefinitionCompressed":"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==","DefinitionCompressed@odata.type":"Edm.Binary","Metadata":"F3t9","Metadata@odata.type":"Edm.Binary","ParametersCompressed":"F3t9","ParametersCompressed@odata.type":"Edm.Binary","ConnectionReferences":"F3t9","ConnectionReferences@odata.type":"Edm.Binary","WorkflowReferences":"F3t9","WorkflowReferences@odata.type":"Edm.Binary","KeyVaultCertificateReferences":"F3t9","KeyVaultCertificateReferences@odata.type":"Edm.Binary","RuntimeContext":"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ","RuntimeContext@odata.type":"Edm.Binary","FlowUpdatedTime":"2021-04-15T23:09:47.4101988Z","FlowUpdatedTime@odata.type":"Edm.DateTime"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey=\'09CEE\',RowKey=\'EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/"datetime\'2021-04-15T23%3A09%3A46.5910000Z\'"\r\n\r\n{"Sku":"{\\"name\\":\\"Standard\\",\\"plan\\":{\\"name\\":\\"farm0\\",\\"id\\":\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\",\\"type\\":\\"Microsoft.Web/ServerFarms\\"}}","State":"Enabled","CreatedTime":"2021-04-15T23:09:46.5446473Z","CreatedTime@odata.type":"Edm.DateTime","ChangedTime":"2021-04-15T23:09:47.4214726Z","ChangedTime@odata.type":"Edm.DateTime","DeletedTime":"1970-01-01T00:00:00Z","DeletedTime@odata.type":"Edm.DateTime","ChangedOperationId":"f2503371-15c7-4314-9803-81ea69f1ca72","FlowId":"5539f65e020b44fca32cf9cbe56e286a","SubscriptionId":"ea5f528c-f1b8-4658-a5ce-cc574848547b","ResourceGroupName":"de415c09-29bb-483d-9544-25602c1ff355","FlowName":"testflow1","FlowSequenceId":"08585830786980800821","ScaleUnit":"CU03","Location":"devfabric","RuntimeConfiguration":"{}","DefinitionCompressed":"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==","DefinitionCompressed@odata.type":"Edm.Binary","Metadata":"F3t9","Metadata@odata.type":"Edm.Binary","ParametersCompressed":"F3t9","ParametersCompressed@odata.type":"Edm.Binary","ConnectionReferences":"F3t9","ConnectionReferences@odata.type":"Edm.Binary","WorkflowReferences":"F3t9","WorkflowReferences@odata.type":"Edm.Binary","KeyVaultCertificateReferences":"F3t9","KeyVaultCertificateReferences@odata.type":"Edm.Binary","RuntimeContext":"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ","RuntimeContext@odata.type":"Edm.Binary","FlowUpdatedTime":"2021-04-15T23:09:47.4101988Z","FlowUpdatedTime@odata.type":"Edm.DateTime"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey=\'09CEE\',RowKey=\'EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1\') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/"datetime\'2021-04-15T23%3A09%3A46.5910000Z\'"\r\n\r\n{"Sku":"{\\"name\\":\\"Standard\\",\\"plan\\":{\\"name\\":\\"farm0\\",\\"id\\":\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\",\\"type\\":\\"Microsoft.Web/ServerFarms\\"}}","State":"Enabled","CreatedTime":"2021-04-15T23:09:46.5446473Z","CreatedTime@odata.type":"Edm.DateTime","ChangedTime":"2021-04-15T23:09:47.4214726Z","ChangedTime@odata.type":"Edm.DateTime","DeletedTime":"1970-01-01T00:00:00Z","DeletedTime@odata.type":"Edm.DateTime","ChangedOperationId":"f2503371-15c7-4314-9803-81ea69f1ca72","FlowId":"5539f65e020b44fca32cf9cbe56e286a","SubscriptionId":"ea5f528c-f1b8-4658-a5ce-cc574848547b","ResourceGroupName":"de415c09-29bb-483d-9544-25602c1ff355","FlowName":"testflow1","FlowSequenceId":"08585830786980800821","ScaleUnit":"CU03","Location":"devfabric","RuntimeConfiguration":"{}","DefinitionCompressed":"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==","DefinitionCompressed@odata.type":"Edm.Binary","Metadata":"F3t9","Metadata@odata.type":"Edm.Binary","ParametersCompressed":"F3t9","ParametersCompressed@odata.type":"Edm.Binary","ConnectionReferences":"F3t9","ConnectionReferences@odata.type":"Edm.Binary","WorkflowReferences":"F3t9","WorkflowReferences@odata.type":"Edm.Binary","KeyVaultCertificateReferences":"F3t9","KeyVaultCertificateReferences@odata.type":"Edm.Binary","RuntimeContext":"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ","RuntimeContext@odata.type":"Edm.Binary","FlowUpdatedTime":"2021-04-15T23:09:47.4101988Z","FlowUpdatedTime@odata.type":"Edm.DateTime"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n--batch_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n`; + + before(async () => { + server = new TableServer(config); + await server.start(); + // requestOverride.headers = { + // Prefer: "return-content", + // accept: "application/json;odata=fullmetadata" + // }; + }); + + after(async () => { + await server.close(); + }); + + // Reproducing the individual errors from the issue 754 + it.only("Should be able to create a table using axios rest client, @loki", (done) => { + // create table + axios + .post( + `${protocol}://${host}:${port}/${accountName}/Tables`, + { + TableName: reproFlowsTableName + }, + axiosRequestConfig(accountName, sharedKey) + ) + .then((res) => { + // repro request 1 + // RequestMethod=POST RequestURL=http://127.0.0.1/devstoreaccount1/$batch?sv=2018-03-28&sig=WTksSlJMYweYOjn0f%2BQ3AzgZlTiFEo9R9Z%2Bv8XnYXYM%3D&se=2023-04-15T23%3A09%3A41Z&srt=sco&ss=bqt&sp=racupwdl&timeout=15 + // RequestHeaders:{"user-agent":"ResourceStack/6.0.0.1260","x-ms-version":"2018-03-28","x-ms-client-request-id":"f2503371-15c7-4314-9803-81ea69f1ca72","accept":"application/json;odata=nometadata","content-type":"multipart/mixed; boundary=batch_3e8c6583-146e-4326-835f-5f7321fc6711","host":"127.0.0.1:10002","content-length":"6865"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1 + axios + .post( + `${protocol}://${host}:${port}/${accountName}/$batch`, + request1RawRequestString, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": + "f2503371-15c7-4314-9803-81ea69f1ca72", + accept: "application/json;odata=nometadata", + "content-type": + "multipart/mixed; boundary=batch_3e8c6583-146e-4326-835f-5f7321fc6711", + host: "127.0.0.1:10002", + "content-length": "6865" + } + } + ) + .then((res2) => { + assert.ok(res); + }) + .catch((err2) => { + assert.ifError(err2); + }); + }) + .catch((err) => { + assert.ifError(err); + }) + .finally(done); + }); + + // https://github.com/Azure/Azurite/issues/754 +}); +function axiosRequestConfig(accountName: string, sharedKey: string) { + return { + headers: { + "Content-Type": "application/json", + Accept: "application/json;odata=nometadata", + Authorization: `SharedKey ${accountName}:${sharedKey}` + } + }; +} + +/* + Text + 2021-04-15T23:09:46.597Z de79bba2-949c-42fe-8228-a0df1c8c8ca5 debug: TableHandler:batch() Raw request string is "--batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: multipart/mixed; boundary=changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\n\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/flows HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/flows HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786989753914\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/flows HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09:2D29BB:2D483D:2D9544:2D25602C1FF355-TESTFLOW1\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n--batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n" + 2021-04-15T23:09:46.603Z de79bba2-949c-42fe-8228-a0df1c8c8ca5 debug: TableHandler:batch() Raw response string is "--batchresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: multipart/mixed; boundary=changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\n\r\n--changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nLocation: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')\r\nDataServiceId: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')\r\nETag: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n\r\n--changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nLocation: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786989753914')\r\nDataServiceId: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786989753914')\r\nETag: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n\r\n--changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nLocation: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09:2D29BB:2D483D:2D9544:2D25602C1FF355-TESTFLOW1')\r\nDataServiceId: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09:2D29BB:2D483D:2D9544:2D25602C1FF355-TESTFLOW1')\r\nETag: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n\r\n--changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n--batchresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n" + 2021-04-15T23:09:46.662Z 543ce3cd-2c6a-4bb5-877f-18ba9700a82d info: TableStorageContextMiddleware: RequestMethod=GET RequestURL=http://127.0.0.1/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')?sv=2018-03-28&sig=WTksSlJMYweYOjn0f%2BQ3AzgZlTiFEo9R9Z%2Bv8XnYXYM%3D&se=2023-04-15T23%3A09%3A41Z&srt=sco&ss=bqt&sp=racupwdl&timeout=15 RequestHeaders:{"user-agent":"ResourceStack/6.0.0.1260","x-ms-version":"2018-03-28","x-ms-client-request-id":"7bbeb6b2-a1c7-4fed-8a3c-80f6b3e7db8c","accept":"application/json;odata=minimalmetadata","host":"127.0.0.1:10002"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1 + 2021-04-15T23:09:46.664Z 543ce3cd-2c6a-4bb5-877f-18ba9700a82d debug: TableHandler:queryEntities() Raw response string is "{\"odata.metadata\":\"http://127.0.0.1:10002/devstoreaccount1/$metadata#flows\",\"odata.etag\":\"W/\\\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\\\"\",\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"Metadata@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"Timestamp@odata.type\":\"Edm.DateTime\",\"Timestamp\":\"2021-04-15T23:09:46.5910000Z\"}" + 2021-04-15T23:09:47.414Z 7b939f45-5537-44b3-9c09-5ce5104a7e7c info: TableStorageContextMiddleware: RequestMethod=GET RequestURL=http://127.0.0.1/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')?sv=2018-03-28&sig=WTksSlJMYweYOjn0f%2BQ3AzgZlTiFEo9R9Z%2Bv8XnYXYM%3D&se=2023-04-15T23%3A09%3A41Z&srt=sco&ss=bqt&sp=racupwdl&timeout=15 RequestHeaders:{"user-agent":"ResourceStack/6.0.0.1260","x-ms-version":"2018-03-28","x-ms-client-request-id":"41eb727e-1f85-4f53-b4e1-2df2628b2903","accept":"application/json;odata=minimalmetadata","host":"127.0.0.1:10002"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1 + 2021-04-15T23:09:47.415Z 7b939f45-5537-44b3-9c09-5ce5104a7e7c debug: TableHandler:queryEntities() Raw response string is "{\"odata.metadata\":\"http://127.0.0.1:10002/devstoreaccount1/$metadata#flows\",\"odata.etag\":\"W/\\\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\\\"\",\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"Metadata@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"Timestamp@odata.type\":\"Edm.DateTime\",\"Timestamp\":\"2021-04-15T23:09:46.5910000Z\"}" + 2021-04-15T23:09:47.423Z 90ad0628-eae6-4735-805f-9f165f0ed245 debug: TableHandler:batch() Raw request string is "--batch_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: multipart/mixed; boundary=changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\n\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/flows HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786980800821\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:47.4209193Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n{\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n{\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n--batch_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n" + 2021-04-15T23:09:47.424Z warn: TableHandler:updateEntity() Incoming PartitionKey:09CEE RowKey:EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A in URL parameters don't align with entity body PartitionKey:undefined RowKey:undefined. + 2021-04-15T23:09:47.450Z 59625f4c-8fb0-4b02-be43-dae752e16b19 info: TableStorageContextMiddleware: RequestMethod=GET RequestURL=http://127.0.0.1/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')?sv=2018-03-28&sig=WTksSlJMYweYOjn0f%2BQ3AzgZlTiFEo9R9Z%2Bv8XnYXYM%3D&se=2023-04-15T23%3A09%3A41Z&srt=sco&ss=bqt&sp=racupwdl&timeout=15 RequestHeaders:{"user-agent":"ResourceStack/6.0.0.1260","x-ms-version":"2018-03-28","x-ms-client-request-id":"ceceedd3-4d7c-450f-a738-b83b21788d42","accept":"application/json;odata=minimalmetadata","host":"127.0.0.1:10002"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1 + 2021-04-15T23:09:47.451Z 59625f4c-8fb0-4b02-be43-dae752e16b19 debug: TableHandler:queryEntities() Raw response string is "{\"odata.metadata\":\"http://127.0.0.1:10002/devstoreaccount1/$metadata#flows\",\"odata.etag\":\"W/\\\"datetime'2021-04-15T23%3A09%3A47.4220000Z'\\\"\",\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"Metadata@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"Timestamp@odata.type\":\"Edm.DateTime\",\"Timestamp\":\"2021-04-15T23:09:47.4220000Z\"}" +*/ From 95a932ec4403bc70faf86fd22ad75c00228a8762 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Mon, 19 Apr 2021 12:59:46 +0200 Subject: [PATCH 45/57] resolved issue --- src/table/batch/TableBatchSerialization.ts | 3 +- .../apis/table.entity.tests.azure.rest.ts | 317 ++++++++++++------ 2 files changed, 216 insertions(+), 104 deletions(-) diff --git a/src/table/batch/TableBatchSerialization.ts b/src/table/batch/TableBatchSerialization.ts index 2b4706ac8..0e4de687c 100644 --- a/src/table/batch/TableBatchSerialization.ts +++ b/src/table/batch/TableBatchSerialization.ts @@ -120,7 +120,8 @@ export class TableBatchSerialization extends BatchSerialization { subStringEnd = subRequest.indexOf(jsonOperationBody[0]); jsonBody = jsonOperationBody[0]; } else { - subStringEnd = subRequest.length - this.changesetBoundary.length - 2; + // remove 1 \r\n + subStringEnd = subRequest.length - 4; jsonBody = ""; } diff --git a/tests/table/apis/table.entity.tests.azure.rest.ts b/tests/table/apis/table.entity.tests.azure.rest.ts index 457fe4a66..aa65599ca 100644 --- a/tests/table/apis/table.entity.tests.azure.rest.ts +++ b/tests/table/apis/table.entity.tests.azure.rest.ts @@ -1,6 +1,8 @@ // Tests in this file are using raw rest requests, // as this enables us to test calls which are otherwise not possible -// using the SDKs +// using the SDKs, can be used as a test rig for repros which provide a debug log. +// later we can automate the parsing of repro logs to automatically play these into the tester +// special care is needed to replace etags when used import * as assert from "assert"; import axios from "axios"; @@ -15,38 +17,16 @@ import { // Set true to enable debug log configLogger(false); -// const partitionKeyForDataTablesTests: string = getUniqueName("datatablestests"); -/** - * Creates an entity for tests, with a randomized row key, - * to avoid conflicts on inserts. - * - * @return {*} {TestEntity} - */ -// const testEntity = { -// Address: "Mountain View", -// Age: 23, -// AmountDue: 200.23, -// "CustomerCode@odata.type": "Edm.Guid", -// CustomerCode: "c9da6455-213d-42c9-9a79-3e9149a57833", -// "CustomerSince@odata.type": "Edm.DateTime", -// CustomerSince: "2008-07-10T00:00:00", -// IsActive: true, -// "NumberOfOrders@odata.type": "Edm.Int64", -// NumberOfOrders: "255", -// PartitionKey: partitionKeyForDataTablesTests, -// RowKey: getUniqueName("row") -// }; - -// class AzureDataTablesTestEntity { -// public partitionKey: string; -// public rowKey: string; -// public myValue: string; -// constructor(part: string, row: string, value: string) { -// this.partitionKey = part; -// this.rowKey = row; -// this.myValue = value; -// } -// } + +function axiosRequestConfig(accountName: string, sharedKey: string) { + return { + headers: { + "Content-Type": "application/json", + Accept: "application/json;odata=nometadata", + Authorization: `SharedKey ${accountName}:${sharedKey}` + } + }; +} describe("table Entity APIs test", () => { // TODO: Create a server factory as tests utils @@ -72,13 +52,12 @@ describe("table Entity APIs test", () => { const accountName = EMULATOR_ACCOUNT_NAME; const sharedKey = EMULATOR_ACCOUNT_KEY; // const tableName: string = getUniqueName("datatables"); - const reproFlowsTableName: string = getUniqueName("flows"); - - const request1RawRequestString: string = `--batch_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: multipart/mixed; boundary=changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\n\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{"PartitionKey":"09CEE","RowKey":"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786980800821","Sku":"{\\"name\\":\\"Standard\\",\\"plan\\":{\\"name\\":\\"farm0\\",\\"id\\":\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\",\\"type\\":\\"Microsoft.Web/ServerFarms\\"}}","State":"Enabled","CreatedTime":"2021-04-15T23:09:47.4209193Z","CreatedTime@odata.type":"Edm.DateTime","ChangedTime":"2021-04-15T23:09:47.4214726Z","ChangedTime@odata.type":"Edm.DateTime","DeletedTime":"1970-01-01T00:00:00Z","DeletedTime@odata.type":"Edm.DateTime","ChangedOperationId":"f2503371-15c7-4314-9803-81ea69f1ca72","FlowId":"5539f65e020b44fca32cf9cbe56e286a","SubscriptionId":"ea5f528c-f1b8-4658-a5ce-cc574848547b","ResourceGroupName":"de415c09-29bb-483d-9544-25602c1ff355","FlowName":"testflow1","FlowSequenceId":"08585830786980800821","ScaleUnit":"CU03","Location":"devfabric","RuntimeConfiguration":"{}","DefinitionCompressed":"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==","DefinitionCompressed@odata.type":"Edm.Binary","Metadata":"F3t9","Metadata@odata.type":"Edm.Binary","ParametersCompressed":"F3t9","ParametersCompressed@odata.type":"Edm.Binary","ConnectionReferences":"F3t9","ConnectionReferences@odata.type":"Edm.Binary","WorkflowReferences":"F3t9","WorkflowReferences@odata.type":"Edm.Binary","KeyVaultCertificateReferences":"F3t9","KeyVaultCertificateReferences@odata.type":"Edm.Binary","RuntimeContext":"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ","RuntimeContext@odata.type":"Edm.Binary","FlowUpdatedTime":"2021-04-15T23:09:47.4101988Z","FlowUpdatedTime@odata.type":"Edm.DateTime"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey=\'09CEE\',RowKey=\'EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/"datetime\'2021-04-15T23%3A09%3A46.5910000Z\'"\r\n\r\n{"Sku":"{\\"name\\":\\"Standard\\",\\"plan\\":{\\"name\\":\\"farm0\\",\\"id\\":\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\",\\"type\\":\\"Microsoft.Web/ServerFarms\\"}}","State":"Enabled","CreatedTime":"2021-04-15T23:09:46.5446473Z","CreatedTime@odata.type":"Edm.DateTime","ChangedTime":"2021-04-15T23:09:47.4214726Z","ChangedTime@odata.type":"Edm.DateTime","DeletedTime":"1970-01-01T00:00:00Z","DeletedTime@odata.type":"Edm.DateTime","ChangedOperationId":"f2503371-15c7-4314-9803-81ea69f1ca72","FlowId":"5539f65e020b44fca32cf9cbe56e286a","SubscriptionId":"ea5f528c-f1b8-4658-a5ce-cc574848547b","ResourceGroupName":"de415c09-29bb-483d-9544-25602c1ff355","FlowName":"testflow1","FlowSequenceId":"08585830786980800821","ScaleUnit":"CU03","Location":"devfabric","RuntimeConfiguration":"{}","DefinitionCompressed":"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==","DefinitionCompressed@odata.type":"Edm.Binary","Metadata":"F3t9","Metadata@odata.type":"Edm.Binary","ParametersCompressed":"F3t9","ParametersCompressed@odata.type":"Edm.Binary","ConnectionReferences":"F3t9","ConnectionReferences@odata.type":"Edm.Binary","WorkflowReferences":"F3t9","WorkflowReferences@odata.type":"Edm.Binary","KeyVaultCertificateReferences":"F3t9","KeyVaultCertificateReferences@odata.type":"Edm.Binary","RuntimeContext":"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ","RuntimeContext@odata.type":"Edm.Binary","FlowUpdatedTime":"2021-04-15T23:09:47.4101988Z","FlowUpdatedTime@odata.type":"Edm.DateTime"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey=\'09CEE\',RowKey=\'EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1\') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/"datetime\'2021-04-15T23%3A09%3A46.5910000Z\'"\r\n\r\n{"Sku":"{\\"name\\":\\"Standard\\",\\"plan\\":{\\"name\\":\\"farm0\\",\\"id\\":\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\",\\"type\\":\\"Microsoft.Web/ServerFarms\\"}}","State":"Enabled","CreatedTime":"2021-04-15T23:09:46.5446473Z","CreatedTime@odata.type":"Edm.DateTime","ChangedTime":"2021-04-15T23:09:47.4214726Z","ChangedTime@odata.type":"Edm.DateTime","DeletedTime":"1970-01-01T00:00:00Z","DeletedTime@odata.type":"Edm.DateTime","ChangedOperationId":"f2503371-15c7-4314-9803-81ea69f1ca72","FlowId":"5539f65e020b44fca32cf9cbe56e286a","SubscriptionId":"ea5f528c-f1b8-4658-a5ce-cc574848547b","ResourceGroupName":"de415c09-29bb-483d-9544-25602c1ff355","FlowName":"testflow1","FlowSequenceId":"08585830786980800821","ScaleUnit":"CU03","Location":"devfabric","RuntimeConfiguration":"{}","DefinitionCompressed":"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==","DefinitionCompressed@odata.type":"Edm.Binary","Metadata":"F3t9","Metadata@odata.type":"Edm.Binary","ParametersCompressed":"F3t9","ParametersCompressed@odata.type":"Edm.Binary","ConnectionReferences":"F3t9","ConnectionReferences@odata.type":"Edm.Binary","WorkflowReferences":"F3t9","WorkflowReferences@odata.type":"Edm.Binary","KeyVaultCertificateReferences":"F3t9","KeyVaultCertificateReferences@odata.type":"Edm.Binary","RuntimeContext":"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ","RuntimeContext@odata.type":"Edm.Binary","FlowUpdatedTime":"2021-04-15T23:09:47.4101988Z","FlowUpdatedTime@odata.type":"Edm.DateTime"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n--batch_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n`; + let reproFlowsTableName: string = "flows"; before(async () => { server = new TableServer(config); await server.start(); + reproFlowsTableName = getUniqueName("flows"); // requestOverride.headers = { // Prefer: "return-content", // accept: "application/json;odata=fullmetadata" @@ -89,74 +68,206 @@ describe("table Entity APIs test", () => { await server.close(); }); - // Reproducing the individual errors from the issue 754 - it.only("Should be able to create a table using axios rest client, @loki", (done) => { - // create table - axios - .post( - `${protocol}://${host}:${port}/${accountName}/Tables`, + // https://github.com/Azure/Azurite/issues/754 + it("Should be able to create a table using axios rest client and await, @loki", async () => { + // first crfeate the table for these tests + // in order to run tests without cleaning up, I am replacing the table name with a unique name each time + const createTableResult = await axios.post( + `${protocol}://${host}:${port}/${accountName}/Tables`, + { + TableName: reproFlowsTableName + }, + axiosRequestConfig(accountName, sharedKey) + ); + // table created for test run OK + assert.strictEqual(createTableResult.status, 201); + + // prettier-ignore + const batchRequest1RawRequestString: string = `--batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: multipart/mixed; boundary=changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\n\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786989753914\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09:2D29BB:2D483D:2D9544:2D25602C1FF355-TESTFLOW1\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n--batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n`; + + const request1Result = await axios.post( + `${protocol}://${host}:${port}/${accountName}/$batch`, + batchRequest1RawRequestString, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "127b472c-6db3-4de7-bdb7-4947314e77c0", + accept: "application/json;odata=nometadata", + "content-type": + "multipart/mixed; boundary=batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7", + host: "127.0.0.1:10002", + "content-length": "6803" + } + } + ); + // we submitted the batch OK + assert.strictEqual(request1Result.status, 202); + + const request2Result = await axios.get( + `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "7bbeb6b2-a1c7-4fed-8a3c-80f6b3e7db8c", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" + } + } + ); + assert.strictEqual(request2Result.status, 200); + + const request3Result = await axios.get( + `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "41eb727e-1f85-4f53-b4e1-2df2628b2903", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" + } + } + ); + assert.strictEqual(request3Result.status, 200); + + // prettier-ignore + const batchRequest2RawRequestString: string = `--batch_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: multipart/mixed; boundary=changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\n\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786980800821\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:47.4209193Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n{\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n{\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n--batch_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n`; + + const request4Result = await axios.post( + `${protocol}://${host}:${port}/${accountName}/$batch`, + batchRequest2RawRequestString, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "f2503371-15c7-4314-9803-81ea69f1ca72", + accept: "application/json;odata=nometadata", + "content-type": + "multipart/mixed; boundary=batch_3e8c6583-146e-4326-835f-5f7321fc6711", + host: "127.0.0.1:10002", + "content-length": "6865" + } + } + ); + // we submitted the batch OK + assert.strictEqual(request4Result.status, 202); + + const request5Result = await axios.get( + `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "ceceedd3-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" + } + } + ); + assert.strictEqual(request5Result.status, 200); + + const request6Result = await axios.get( + `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "ceceedd3-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" + } + } + ); + assert.strictEqual(request6Result.status, 200); + const result6Data: any = request6Result.data; + // prettier-ignore + const flowEtag: string = result6Data["odata.etag"]; + + // we need to look up EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1 + // as this etag is also used with the delete in the failing batch request + const requestTestFlowResult = await axios.get( + `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1')`, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "00000000-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" + } + } + ); + assert.strictEqual(requestTestFlowResult.status, 200); + const resultTestFlowData: any = request6Result.data; + // prettier-ignore + const testFlowEtag: string = resultTestFlowData["odata.etag"]; + + // validate the etag that we are using to delete the flow + const validateEtagResult = await axios.get( + `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "00000001-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" + } + } + ); + assert.strictEqual(request6Result.status, 200); + const validateEtagResultData: any = validateEtagResult.data; + // prettier-ignore + const flowEtagValid: string = validateEtagResultData["odata.etag"]; + + assert.strictEqual( + flowEtag, + flowEtagValid, + "The Etag from the batch request and the etag we have in storage do not match!" + ); + + // we need to replace the if-match / etag with the one from request6 + // prettier-ignore + const batchRequest3RawRequestString: string = `--batch_558d985f-491c-496d-b4a2-311c3e1e075d\r\nContent-Type: multipart/mixed; boundary=changeset_558d985f-491c-496d-b4a2-311c3e1e075d\r\n\r\n--changeset_558d985f-491c-496d-b4a2-311c3e1e075d\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nDELETE http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: ${flowEtag}\r\n\r\n--changeset_558d985f-491c-496d-b4a2-311c3e1e075d\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nDELETE http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: ${testFlowEtag}\r\n\r\n--changeset_558d985f-491c-496d-b4a2-311c3e1e075d--\r\n--batch_558d985f-491c-496d-b4a2-311c3e1e075d--\r\n`; + + const request7Result = await axios.post( + `${protocol}://${host}:${port}/${accountName}/$batch`, + batchRequest3RawRequestString, + { + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "41aef06f-9443-497e-b192-216ae988549b", + "content-type": + "multipart/mixed; boundary=batch_558d985f-491c-496d-b4a2-311c3e1e075d", + accept: "application/json;odata=nometadata", + host: "127.0.0.1:10002", + "content-length": "1120" + } + } + ); + // we submitted the batch OK + // current repro fails with precondition failed + assert.strictEqual(request7Result.status, 202); + + // validate the object was deleted! + await axios + .get( + `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, { - TableName: reproFlowsTableName - }, - axiosRequestConfig(accountName, sharedKey) + headers: { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "00000002-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" + } + } ) - .then((res) => { - // repro request 1 - // RequestMethod=POST RequestURL=http://127.0.0.1/devstoreaccount1/$batch?sv=2018-03-28&sig=WTksSlJMYweYOjn0f%2BQ3AzgZlTiFEo9R9Z%2Bv8XnYXYM%3D&se=2023-04-15T23%3A09%3A41Z&srt=sco&ss=bqt&sp=racupwdl&timeout=15 - // RequestHeaders:{"user-agent":"ResourceStack/6.0.0.1260","x-ms-version":"2018-03-28","x-ms-client-request-id":"f2503371-15c7-4314-9803-81ea69f1ca72","accept":"application/json;odata=nometadata","content-type":"multipart/mixed; boundary=batch_3e8c6583-146e-4326-835f-5f7321fc6711","host":"127.0.0.1:10002","content-length":"6865"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1 - axios - .post( - `${protocol}://${host}:${port}/${accountName}/$batch`, - request1RawRequestString, - { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": - "f2503371-15c7-4314-9803-81ea69f1ca72", - accept: "application/json;odata=nometadata", - "content-type": - "multipart/mixed; boundary=batch_3e8c6583-146e-4326-835f-5f7321fc6711", - host: "127.0.0.1:10002", - "content-length": "6865" - } - } - ) - .then((res2) => { - assert.ok(res); - }) - .catch((err2) => { - assert.ifError(err2); - }); - }) - .catch((err) => { - assert.ifError(err); - }) - .finally(done); + .catch((getErr) => { + assert.strictEqual(getErr.response.status, 404); + }); }); - - // https://github.com/Azure/Azurite/issues/754 }); -function axiosRequestConfig(accountName: string, sharedKey: string) { - return { - headers: { - "Content-Type": "application/json", - Accept: "application/json;odata=nometadata", - Authorization: `SharedKey ${accountName}:${sharedKey}` - } - }; -} - -/* - Text - 2021-04-15T23:09:46.597Z de79bba2-949c-42fe-8228-a0df1c8c8ca5 debug: TableHandler:batch() Raw request string is "--batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: multipart/mixed; boundary=changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\n\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/flows HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/flows HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786989753914\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/flows HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09:2D29BB:2D483D:2D9544:2D25602C1FF355-TESTFLOW1\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n--batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n" - 2021-04-15T23:09:46.603Z de79bba2-949c-42fe-8228-a0df1c8c8ca5 debug: TableHandler:batch() Raw response string is "--batchresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: multipart/mixed; boundary=changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\n\r\n--changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nLocation: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')\r\nDataServiceId: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')\r\nETag: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n\r\n--changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nLocation: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786989753914')\r\nDataServiceId: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786989753914')\r\nETag: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n\r\n--changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nHTTP/1.1 204 No Content\r\nX-Content-Type-Options: nosniff\r\nCache-Control: no-cache\r\nLocation: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09:2D29BB:2D483D:2D9544:2D25602C1FF355-TESTFLOW1')\r\nDataServiceId: http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09:2D29BB:2D483D:2D9544:2D25602C1FF355-TESTFLOW1')\r\nETag: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n\r\n--changesetresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n--batchresponse_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n" - 2021-04-15T23:09:46.662Z 543ce3cd-2c6a-4bb5-877f-18ba9700a82d info: TableStorageContextMiddleware: RequestMethod=GET RequestURL=http://127.0.0.1/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')?sv=2018-03-28&sig=WTksSlJMYweYOjn0f%2BQ3AzgZlTiFEo9R9Z%2Bv8XnYXYM%3D&se=2023-04-15T23%3A09%3A41Z&srt=sco&ss=bqt&sp=racupwdl&timeout=15 RequestHeaders:{"user-agent":"ResourceStack/6.0.0.1260","x-ms-version":"2018-03-28","x-ms-client-request-id":"7bbeb6b2-a1c7-4fed-8a3c-80f6b3e7db8c","accept":"application/json;odata=minimalmetadata","host":"127.0.0.1:10002"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1 - 2021-04-15T23:09:46.664Z 543ce3cd-2c6a-4bb5-877f-18ba9700a82d debug: TableHandler:queryEntities() Raw response string is "{\"odata.metadata\":\"http://127.0.0.1:10002/devstoreaccount1/$metadata#flows\",\"odata.etag\":\"W/\\\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\\\"\",\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"Metadata@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"Timestamp@odata.type\":\"Edm.DateTime\",\"Timestamp\":\"2021-04-15T23:09:46.5910000Z\"}" - 2021-04-15T23:09:47.414Z 7b939f45-5537-44b3-9c09-5ce5104a7e7c info: TableStorageContextMiddleware: RequestMethod=GET RequestURL=http://127.0.0.1/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')?sv=2018-03-28&sig=WTksSlJMYweYOjn0f%2BQ3AzgZlTiFEo9R9Z%2Bv8XnYXYM%3D&se=2023-04-15T23%3A09%3A41Z&srt=sco&ss=bqt&sp=racupwdl&timeout=15 RequestHeaders:{"user-agent":"ResourceStack/6.0.0.1260","x-ms-version":"2018-03-28","x-ms-client-request-id":"41eb727e-1f85-4f53-b4e1-2df2628b2903","accept":"application/json;odata=minimalmetadata","host":"127.0.0.1:10002"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1 - 2021-04-15T23:09:47.415Z 7b939f45-5537-44b3-9c09-5ce5104a7e7c debug: TableHandler:queryEntities() Raw response string is "{\"odata.metadata\":\"http://127.0.0.1:10002/devstoreaccount1/$metadata#flows\",\"odata.etag\":\"W/\\\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\\\"\",\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"Metadata@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"Timestamp@odata.type\":\"Edm.DateTime\",\"Timestamp\":\"2021-04-15T23:09:46.5910000Z\"}" - 2021-04-15T23:09:47.423Z 90ad0628-eae6-4735-805f-9f165f0ed245 debug: TableHandler:batch() Raw request string is "--batch_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: multipart/mixed; boundary=changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\n\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/flows HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786980800821\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:47.4209193Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n{\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n{\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n--batch_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n" - 2021-04-15T23:09:47.424Z warn: TableHandler:updateEntity() Incoming PartitionKey:09CEE RowKey:EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A in URL parameters don't align with entity body PartitionKey:undefined RowKey:undefined. - 2021-04-15T23:09:47.450Z 59625f4c-8fb0-4b02-be43-dae752e16b19 info: TableStorageContextMiddleware: RequestMethod=GET RequestURL=http://127.0.0.1/devstoreaccount1/flows(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')?sv=2018-03-28&sig=WTksSlJMYweYOjn0f%2BQ3AzgZlTiFEo9R9Z%2Bv8XnYXYM%3D&se=2023-04-15T23%3A09%3A41Z&srt=sco&ss=bqt&sp=racupwdl&timeout=15 RequestHeaders:{"user-agent":"ResourceStack/6.0.0.1260","x-ms-version":"2018-03-28","x-ms-client-request-id":"ceceedd3-4d7c-450f-a738-b83b21788d42","accept":"application/json;odata=minimalmetadata","host":"127.0.0.1:10002"} ClientIP=127.0.0.1 Protocol=http HTTPVersion=1.1 - 2021-04-15T23:09:47.451Z 59625f4c-8fb0-4b02-be43-dae752e16b19 debug: TableHandler:queryEntities() Raw response string is "{\"odata.metadata\":\"http://127.0.0.1:10002/devstoreaccount1/$metadata#flows\",\"odata.etag\":\"W/\\\"datetime'2021-04-15T23%3A09%3A47.4220000Z'\\\"\",\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"Metadata@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"Timestamp@odata.type\":\"Edm.DateTime\",\"Timestamp\":\"2021-04-15T23:09:47.4220000Z\"}" -*/ From 4077b75350106da6b6b5ab4a50bc159d0d6fa7a0 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Mon, 19 Apr 2021 20:05:45 +0200 Subject: [PATCH 46/57] added documentation for table testing --- tests/table/apis/table-api-testing.md | 48 +++++++++++++++++++ .../apis/table.entity.tests.azure.rest.ts | 1 + 2 files changed, 49 insertions(+) create mode 100644 tests/table/apis/table-api-testing.md diff --git a/tests/table/apis/table-api-testing.md b/tests/table/apis/table-api-testing.md new file mode 100644 index 000000000..17b18a226 --- /dev/null +++ b/tests/table/apis/table-api-testing.md @@ -0,0 +1,48 @@ +# Table API Testing + +## Overview + +There are a few different test options for the Table APIs. + +### Azure Storage SDK + +https://www.npmjs.com/package/azure-storage +https://github.com/Azure/azure-storage-node + +At the time of writing, this was using: + +```json + "azure-storage": "^2.10.3" +``` + +This is the "legacy" storage SDK. +Initial Entity tests were written using this SDK for convenience sake. +v10 no longer supports Table API. + +### Azure Data-Tables SDK + +https://www.npmjs.com/package/@azure/data-tables +https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/tables/data-tables + +At the time of writing, actively maintained. +Provides more support for Batch / entity group transactions than the legacy SDK. + +```json +"@azure/data-tables": "^12.0.0-beta.2", +``` + +Long term, new tests should be written using the data-tables package. + +### HTTP Rest testing + +At the time of writing, this is using the axios package: + +```json + "axios": "^0.21.1", +``` + +These tests take the raw HTTP request information from the debug logs, which include body and header information, and replay these against Azurite to enable easier repros of issues raised by the community. + +Eventually, a more automated replay would be desirable, which can replay a log file created by someone with an issue. + +Care is currently needed to ensure that the tables used by clients are created with unique keys, and that these are replaced in subsequent requests. diff --git a/tests/table/apis/table.entity.tests.azure.rest.ts b/tests/table/apis/table.entity.tests.azure.rest.ts index aa65599ca..fc417908f 100644 --- a/tests/table/apis/table.entity.tests.azure.rest.ts +++ b/tests/table/apis/table.entity.tests.azure.rest.ts @@ -18,6 +18,7 @@ import { // Set true to enable debug log configLogger(false); +// need to create the shared key function axiosRequestConfig(accountName: string, sharedKey: string) { return { headers: { From 9ef4cc85b569dc19fd1719b5dc84ad750ba0b7c4 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Mon, 19 Apr 2021 20:08:46 +0200 Subject: [PATCH 47/57] updated documentation for table testing --- tests/table/apis/table-api-testing.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/table/apis/table-api-testing.md b/tests/table/apis/table-api-testing.md index 17b18a226..14b0a8c66 100644 --- a/tests/table/apis/table-api-testing.md +++ b/tests/table/apis/table-api-testing.md @@ -35,6 +35,9 @@ Long term, new tests should be written using the data-tables package. ### HTTP Rest testing +https://www.npmjs.com/package/axios +https://github.com/axios/axios + At the time of writing, this is using the axios package: ```json From 1daa360548e8e921ab996496cc2ba9c8122f7097 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Mon, 19 Apr 2021 20:54:28 +0200 Subject: [PATCH 48/57] updated testing, sharedkeylit implementation not quite finished for rest --- src/table/TableRequestListenerFactory.ts | 14 +- .../apis/table.entity.tests.azure.rest.ts | 132 +++++++++++++++- .../apis/table.entity.tests.utils.for.rest.ts | 143 ++++++++++++++++++ 3 files changed, 276 insertions(+), 13 deletions(-) create mode 100644 tests/table/apis/table.entity.tests.utils.for.rest.ts diff --git a/src/table/TableRequestListenerFactory.ts b/src/table/TableRequestListenerFactory.ts index 077e819ee..f66dfa03b 100644 --- a/src/table/TableRequestListenerFactory.ts +++ b/src/table/TableRequestListenerFactory.ts @@ -75,7 +75,6 @@ export default class TableRequestListenerFactory // TODO: Override Query Table JSON response element value TableQueryResponse.type.modelProperties!.value.xmlElementName = "value"; - const useAuth = false; const app = express().disable("x-powered-by"); // MiddlewareFactory is a factory to create auto-generated middleware @@ -124,13 +123,12 @@ export default class TableRequestListenerFactory logger ) ]; - if (useAuth) { - app.use( - authenticationMiddlewareFactory.createAuthenticationMiddleware( - authenticators - ) - ); - } + + app.use( + authenticationMiddlewareFactory.createAuthenticationMiddleware( + authenticators + ) + ); // Generated, will do basic validation defined in swagger app.use(middlewareFactory.createDeserializerMiddleware()); diff --git a/tests/table/apis/table.entity.tests.azure.rest.ts b/tests/table/apis/table.entity.tests.azure.rest.ts index fc417908f..829b30b42 100644 --- a/tests/table/apis/table.entity.tests.azure.rest.ts +++ b/tests/table/apis/table.entity.tests.azure.rest.ts @@ -7,8 +7,10 @@ import * as assert from "assert"; import axios from "axios"; import { configLogger } from "../../../src/common/Logger"; +import { computeHMACSHA256 } from "../../../src/common/utils/utils"; import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; +import { HeaderConstants } from "../../../src/table/utils/constants"; import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME, @@ -18,17 +20,138 @@ import { // Set true to enable debug log configLogger(false); +const accountName = EMULATOR_ACCOUNT_NAME; +const sharedKey = EMULATOR_ACCOUNT_KEY; +const key1 = Buffer.from(sharedKey, "base64"); // need to create the shared key -function axiosRequestConfig(accountName: string, sharedKey: string) { +// using SharedKeyLite as it is quick and easy +function axiosRequestConfig(stringToSign: string) { + const signature1 = computeHMACSHA256(stringToSign, key1); + const authValue = `SharedKeyLite ${accountName}:${signature1}`; return { headers: { "Content-Type": "application/json", Accept: "application/json;odata=nometadata", - Authorization: `SharedKey ${accountName}:${sharedKey}` + Authorization: authValue } }; } +function signContent(url: string, headers: any) { + const stringToSign: string = + [ + getHeaderValueToSign(HeaderConstants.DATE, headers) || + getHeaderValueToSign(HeaderConstants.X_MS_DATE, headers) + ].join("\n") + + "\n" + + getCanonicalizedResourceString( + url, + accountName, + "/devstoreaccount1/Tables" + ); + + return stringToSign; +} + +/** + * Retrieve header value according to shared key sign rules. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + * + * @private + * @param {WebResource} request + * @param {string} headerName + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ +function getHeaderValueToSign(headerName: string, headers: any): string { + const value = headers[headerName]; + + if (!value) { + return ""; + } + + // When using version 2015-02-21 or later, if Content-Length is zero, then + // set the Content-Length part of the StringToSign to an empty string. + // https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + if (headerName === HeaderConstants.CONTENT_LENGTH && value === "0") { + return ""; + } + + return value; +} + +/** + * Retrieves canonicalized resource string. + * + * @private + * @param {IRequest} request + * @returns {string} + */ +function getCanonicalizedResourceString( + url: string, + account: string, + authenticationPath?: string +): string { + let path = getPath(url) || "/"; + + // For secondary account, we use account name (without "-secondary") for the path + if (authenticationPath !== undefined) { + path = authenticationPath; + } + + let canonicalizedResourceString: string = ""; + canonicalizedResourceString += `/${account}${path}`; + + const queries = getURLQueries(url); + const lowercaseQueries: { [key: string]: string } = {}; + if (queries) { + const queryKeys: string[] = []; + for (const key in queries) { + if (queries.hasOwnProperty(key)) { + const lowercaseKey = key.toLowerCase(); + lowercaseQueries[lowercaseKey] = queries[key]; + queryKeys.push(lowercaseKey); + } + } + + if (queryKeys.includes("comp")) { + canonicalizedResourceString += "?comp=" + lowercaseQueries.comp; + } + + // queryKeys.sort(); + // for (const key of queryKeys) { + // canonicalizedResourceString += `\n${key}:${decodeURIComponent( + // lowercaseQueries[key] + // )}`; + // } + } + + return canonicalizedResourceString; +} + +/** + * Retrieves path from URL. + * + * @private + * @param {string} url + * @returns {string} + */ +function getPath(url: string): string { + return url; +} + +/** + * Retrieves queries from URL. + * + * @private + * @param {string} url + * @returns {string} + */ +function getURLQueries(url: string): { [key: string]: string } { + const lowercaseQueries: { [key: string]: string } = {}; + return lowercaseQueries; +} + describe("table Entity APIs test", () => { // TODO: Create a server factory as tests utils const protocol = "http"; @@ -50,8 +173,7 @@ describe("table Entity APIs test", () => { ); let server: TableServer; - const accountName = EMULATOR_ACCOUNT_NAME; - const sharedKey = EMULATOR_ACCOUNT_KEY; + // const tableName: string = getUniqueName("datatables"); let reproFlowsTableName: string = "flows"; @@ -78,7 +200,7 @@ describe("table Entity APIs test", () => { { TableName: reproFlowsTableName }, - axiosRequestConfig(accountName, sharedKey) + axiosRequestConfig(sharedKey) ); // table created for test run OK assert.strictEqual(createTableResult.status, 201); diff --git a/tests/table/apis/table.entity.tests.utils.for.rest.ts b/tests/table/apis/table.entity.tests.utils.for.rest.ts new file mode 100644 index 000000000..b476a7322 --- /dev/null +++ b/tests/table/apis/table.entity.tests.utils.for.rest.ts @@ -0,0 +1,143 @@ +import { computeHMACSHA256 } from "../../../src/common/utils/utils"; +import { HeaderConstants } from "../../../src/table/utils/constants"; +import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME } from "../../testutils"; + +export const accountName = EMULATOR_ACCOUNT_NAME; +export const sharedKey = EMULATOR_ACCOUNT_KEY; +const key1 = Buffer.from(sharedKey, "base64"); +// need to create the shared key +// using SharedKeyLite as it is quick and easy +export function axiosRequestConfig(stringToSign: string) { + const signature1 = computeHMACSHA256(stringToSign, key1); + const authValue = `SharedKeyLite ${accountName}:${signature1}`; + return { + headers: { + "Content-Type": "application/json", + Accept: "application/json;odata=nometadata", + Authorization: authValue + } + }; +} + +/** + * Create signed value according to shared key lite sign rules. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + * + * @private + * @param {string} url + * @param {any} headers + * @returns {string} + */ +export function createSignatureForSharedKeyLite( + url: string, + headers: any +): string { + const stringToSign: string = + [ + getHeaderValueToSign(HeaderConstants.DATE, headers) || + getHeaderValueToSign(HeaderConstants.X_MS_DATE, headers) + ].join("\n") + + "\n" + + getCanonicalizedResourceString( + url, + accountName, + "/devstoreaccount1/Tables" + ); + + return stringToSign; +} +/** + * Retrieve header value according to shared key sign rules. + * @see https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + * + * @private + * @param {WebResource} request + * @param {string} headerName + * @returns {string} + * @memberof SharedKeyCredentialPolicy + */ +function getHeaderValueToSign(headerName: string, headers: any): string { + const value = headers[headerName]; + + if (!value) { + return ""; + } + + // When using version 2015-02-21 or later, if Content-Length is zero, then + // set the Content-Length part of the StringToSign to an empty string. + // https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key + if (headerName === HeaderConstants.CONTENT_LENGTH && value === "0") { + return ""; + } + + return value; +} +/** + * Retrieves canonicalized resource string. + * + * @private + * @param {IRequest} request + * @returns {string} + */ +export function getCanonicalizedResourceString( + url: string, + account: string, + authenticationPath?: string +): string { + let path = getPath(url) || "/"; + + // For secondary account, we use account name (without "-secondary") for the path + if (authenticationPath !== undefined) { + path = authenticationPath; + } + + let canonicalizedResourceString: string = ""; + canonicalizedResourceString += `/${account}${path}`; + + const queries = getURLQueries(url); + const lowercaseQueries: { [key: string]: string } = {}; + if (queries) { + const queryKeys: string[] = []; + for (const key in queries) { + if (queries.hasOwnProperty(key)) { + const lowercaseKey = key.toLowerCase(); + lowercaseQueries[lowercaseKey] = queries[key]; + queryKeys.push(lowercaseKey); + } + } + + if (queryKeys.includes("comp")) { + canonicalizedResourceString += "?comp=" + lowercaseQueries.comp; + } + + // queryKeys.sort(); + // for (const key of queryKeys) { + // canonicalizedResourceString += `\n${key}:${decodeURIComponent( + // lowercaseQueries[key] + // )}`; + // } + } + + return canonicalizedResourceString; +} +/** + * Retrieves path from URL. + * + * @private + * @param {string} url + * @returns {string} + */ +function getPath(url: string): string { + return url; +} +/** + * Retrieves queries from URL. + * + * @private + * @param {string} url + * @returns {string} + */ +function getURLQueries(url: string): { [key: string]: string } { + const lowercaseQueries: { [key: string]: string } = {}; + return lowercaseQueries; +} From f12fe199b23990da0eb52d9a411ce1586ce2e047 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Mon, 19 Apr 2021 20:54:52 +0200 Subject: [PATCH 49/57] updated testing, sharedkeylit implementation not quite finished for rest --- .../apis/table.entity.tests.azure.rest.ts | 150 +----------------- 1 file changed, 6 insertions(+), 144 deletions(-) diff --git a/tests/table/apis/table.entity.tests.azure.rest.ts b/tests/table/apis/table.entity.tests.azure.rest.ts index 829b30b42..03b919804 100644 --- a/tests/table/apis/table.entity.tests.azure.rest.ts +++ b/tests/table/apis/table.entity.tests.azure.rest.ts @@ -2,156 +2,23 @@ // as this enables us to test calls which are otherwise not possible // using the SDKs, can be used as a test rig for repros which provide a debug log. // later we can automate the parsing of repro logs to automatically play these into the tester -// special care is needed to replace etags when used +// special care is needed to replace etags and folders when used import * as assert from "assert"; import axios from "axios"; import { configLogger } from "../../../src/common/Logger"; -import { computeHMACSHA256 } from "../../../src/common/utils/utils"; import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; -import { HeaderConstants } from "../../../src/table/utils/constants"; +import { getUniqueName } from "../../testutils"; import { - EMULATOR_ACCOUNT_KEY, - EMULATOR_ACCOUNT_NAME, - getUniqueName -} from "../../testutils"; + accountName, + axiosRequestConfig, + sharedKey +} from "./table.entity.tests.utils.for.rest"; // Set true to enable debug log configLogger(false); -const accountName = EMULATOR_ACCOUNT_NAME; -const sharedKey = EMULATOR_ACCOUNT_KEY; -const key1 = Buffer.from(sharedKey, "base64"); -// need to create the shared key -// using SharedKeyLite as it is quick and easy -function axiosRequestConfig(stringToSign: string) { - const signature1 = computeHMACSHA256(stringToSign, key1); - const authValue = `SharedKeyLite ${accountName}:${signature1}`; - return { - headers: { - "Content-Type": "application/json", - Accept: "application/json;odata=nometadata", - Authorization: authValue - } - }; -} - -function signContent(url: string, headers: any) { - const stringToSign: string = - [ - getHeaderValueToSign(HeaderConstants.DATE, headers) || - getHeaderValueToSign(HeaderConstants.X_MS_DATE, headers) - ].join("\n") + - "\n" + - getCanonicalizedResourceString( - url, - accountName, - "/devstoreaccount1/Tables" - ); - - return stringToSign; -} - -/** - * Retrieve header value according to shared key sign rules. - * @see https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key - * - * @private - * @param {WebResource} request - * @param {string} headerName - * @returns {string} - * @memberof SharedKeyCredentialPolicy - */ -function getHeaderValueToSign(headerName: string, headers: any): string { - const value = headers[headerName]; - - if (!value) { - return ""; - } - - // When using version 2015-02-21 or later, if Content-Length is zero, then - // set the Content-Length part of the StringToSign to an empty string. - // https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key - if (headerName === HeaderConstants.CONTENT_LENGTH && value === "0") { - return ""; - } - - return value; -} - -/** - * Retrieves canonicalized resource string. - * - * @private - * @param {IRequest} request - * @returns {string} - */ -function getCanonicalizedResourceString( - url: string, - account: string, - authenticationPath?: string -): string { - let path = getPath(url) || "/"; - - // For secondary account, we use account name (without "-secondary") for the path - if (authenticationPath !== undefined) { - path = authenticationPath; - } - - let canonicalizedResourceString: string = ""; - canonicalizedResourceString += `/${account}${path}`; - - const queries = getURLQueries(url); - const lowercaseQueries: { [key: string]: string } = {}; - if (queries) { - const queryKeys: string[] = []; - for (const key in queries) { - if (queries.hasOwnProperty(key)) { - const lowercaseKey = key.toLowerCase(); - lowercaseQueries[lowercaseKey] = queries[key]; - queryKeys.push(lowercaseKey); - } - } - - if (queryKeys.includes("comp")) { - canonicalizedResourceString += "?comp=" + lowercaseQueries.comp; - } - - // queryKeys.sort(); - // for (const key of queryKeys) { - // canonicalizedResourceString += `\n${key}:${decodeURIComponent( - // lowercaseQueries[key] - // )}`; - // } - } - - return canonicalizedResourceString; -} - -/** - * Retrieves path from URL. - * - * @private - * @param {string} url - * @returns {string} - */ -function getPath(url: string): string { - return url; -} - -/** - * Retrieves queries from URL. - * - * @private - * @param {string} url - * @returns {string} - */ -function getURLQueries(url: string): { [key: string]: string } { - const lowercaseQueries: { [key: string]: string } = {}; - return lowercaseQueries; -} - describe("table Entity APIs test", () => { // TODO: Create a server factory as tests utils const protocol = "http"; @@ -174,17 +41,12 @@ describe("table Entity APIs test", () => { let server: TableServer; - // const tableName: string = getUniqueName("datatables"); let reproFlowsTableName: string = "flows"; before(async () => { server = new TableServer(config); await server.start(); reproFlowsTableName = getUniqueName("flows"); - // requestOverride.headers = { - // Prefer: "return-content", - // accept: "application/json;odata=fullmetadata" - // }; }); after(async () => { From c0f5f562988e1424235306ffdd089d579ff0e444 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Tue, 20 Apr 2021 10:12:06 +0200 Subject: [PATCH 50/57] updated test to use encoding on apostrophe in path for signed string in shared key lite auth --- package.json | 2 +- tests/table/apis/table.entity.test.config.ts | 14 ++ tests/table/apis/table.entity.test.ts | 2 +- .../apis/table.entity.tests.rest.submitter.ts | 48 ++++ ...ure.rest.ts => table.entity.tests.rest.ts} | 223 ++++++++---------- .../apis/table.entity.tests.utils.for.rest.ts | 60 ++--- 6 files changed, 197 insertions(+), 152 deletions(-) create mode 100644 tests/table/apis/table.entity.test.config.ts create mode 100644 tests/table/apis/table.entity.tests.rest.submitter.ts rename tests/table/apis/{table.entity.tests.azure.rest.ts => table.entity.tests.rest.ts} (77%) diff --git a/package.json b/package.json index c555e1f03..2a9f6cdf4 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "azurite-table": "./dist/src/table/main.js" }, "engines": { - "node": ">=8.0.0", + "node": ">=10.0.0", "vscode": "^1.39.0" }, "dependencies": { diff --git a/tests/table/apis/table.entity.test.config.ts b/tests/table/apis/table.entity.test.config.ts new file mode 100644 index 000000000..2593cea01 --- /dev/null +++ b/tests/table/apis/table.entity.test.config.ts @@ -0,0 +1,14 @@ +// Provides configuration for table entity tests + +import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME } from "../../testutils"; + +export default class TableEntityTestConfig { + public static protocol: string = "http"; + public static host: string = "127.0.0.1"; + public static port: number = 11002; + public static metadataDbPath = "__tableTestsStorage__"; + public static enableDebugLog: boolean = true; + public static debugLogPath: string = "g:/debug.log"; + public static accountName: string = EMULATOR_ACCOUNT_NAME; + public static sharedKey: string = EMULATOR_ACCOUNT_KEY; +} diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index b4f2be7a3..bbbef5e3b 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -115,7 +115,7 @@ describe("table Entity APIs test", () => { }); // Insert entity property with type "Edm.DateTime", server will convert to UTC time - it("Insert new Entity property with type Edm.DateTime will convert to UTC, @loki", (done) => { + it.only("Insert new Entity property with type Edm.DateTime will convert to UTC, @loki", (done) => { const timeValue = "2012-01-02T23:00:00"; const entity = { PartitionKey: "part1", diff --git a/tests/table/apis/table.entity.tests.rest.submitter.ts b/tests/table/apis/table.entity.tests.rest.submitter.ts new file mode 100644 index 000000000..e8482c229 --- /dev/null +++ b/tests/table/apis/table.entity.tests.rest.submitter.ts @@ -0,0 +1,48 @@ +// This class provides a simple abstraction, and accepts the +// body and headers from debug logs for resubmission and repro + +import axios, { AxiosResponse } from "axios"; +import TableEntityTestConfig from "./table.entity.test.config"; +import { axiosRequestConfig } from "./table.entity.tests.utils.for.rest"; + +/** + * Submits POST request to Azurite table service on the path given + * This could be modified to accept the entire URL, rather than just path + * ToDo: Need to consider cases with query strings etc. + * + * @export + * @param {string} path + * @param {string} body + * @param {*} headers + * @return {Promise} + */ +export async function postToAzurite( + path: string, + body: string, + headers: any +): Promise> { + const url = `${TableEntityTestConfig.protocol}://${TableEntityTestConfig.host}:${TableEntityTestConfig.port}/${TableEntityTestConfig.accountName}/${path}`; + const requestConfig = axiosRequestConfig(url, path, headers); + const result = await axios.post(url, body, requestConfig); + return result; +} + +/** + * Submits POST request to Azurite table service on the path given + * This could be modified to accept the entire URL, rather than just path + * ToDo: Need to consider cases with query strings etc. + * + * @export + * @param {string} path + * @param {*} headers + * @return {Promise} + */ +export async function getToAzurite( + path: string, + headers: any +): Promise> { + const url = `${TableEntityTestConfig.protocol}://${TableEntityTestConfig.host}:${TableEntityTestConfig.port}/${TableEntityTestConfig.accountName}/${path}`; + const requestConfig = axiosRequestConfig(url, path, headers); + const result = await axios.get(url, requestConfig); + return result; +} diff --git a/tests/table/apis/table.entity.tests.azure.rest.ts b/tests/table/apis/table.entity.tests.rest.ts similarity index 77% rename from tests/table/apis/table.entity.tests.azure.rest.ts rename to tests/table/apis/table.entity.tests.rest.ts index 03b919804..1303dff79 100644 --- a/tests/table/apis/table.entity.tests.azure.rest.ts +++ b/tests/table/apis/table.entity.tests.rest.ts @@ -5,23 +5,20 @@ // special care is needed to replace etags and folders when used import * as assert from "assert"; -import axios from "axios"; import { configLogger } from "../../../src/common/Logger"; import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; import { getUniqueName } from "../../testutils"; import { - accountName, - axiosRequestConfig, - sharedKey -} from "./table.entity.tests.utils.for.rest"; + getToAzurite, + postToAzurite +} from "./table.entity.tests.rest.submitter"; // Set true to enable debug log configLogger(false); describe("table Entity APIs test", () => { // TODO: Create a server factory as tests utils - const protocol = "http"; const host = "127.0.0.1"; const port = 11002; const metadataDbPath = "__tableTestsStorage__"; @@ -57,62 +54,60 @@ describe("table Entity APIs test", () => { it("Should be able to create a table using axios rest client and await, @loki", async () => { // first crfeate the table for these tests // in order to run tests without cleaning up, I am replacing the table name with a unique name each time - const createTableResult = await axios.post( - `${protocol}://${host}:${port}/${accountName}/Tables`, - { - TableName: reproFlowsTableName - }, - axiosRequestConfig(sharedKey) + const body = JSON.stringify({ + TableName: reproFlowsTableName + }); + const createTableHeaders = { + "Content-Type": "application/json", + Accept: "application/json;odata=nometadata" + }; + const createTableResult = await postToAzurite( + "Tables", + body, + createTableHeaders ); - // table created for test run OK assert.strictEqual(createTableResult.status, 201); // prettier-ignore const batchRequest1RawRequestString: string = `--batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: multipart/mixed; boundary=changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\n\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786989753914\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09:2D29BB:2D483D:2D9544:2D25602C1FF355-TESTFLOW1\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:46.5535366Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"127b472c-6db3-4de7-bdb7-4947314e77c0\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786989753914\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:46.5430732Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n--batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7--\r\n`; - - const request1Result = await axios.post( - `${protocol}://${host}:${port}/${accountName}/$batch`, + const batchRequest1Headers = { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "127b472c-6db3-4de7-bdb7-4947314e77c0", + accept: "application/json;odata=nometadata", + "content-type": + "multipart/mixed; boundary=batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7", + host: "127.0.0.1:10002", + "content-length": "6803" + }; + const request1Result = await postToAzurite( + "$batch", batchRequest1RawRequestString, - { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "127b472c-6db3-4de7-bdb7-4947314e77c0", - accept: "application/json;odata=nometadata", - "content-type": - "multipart/mixed; boundary=batch_4689afd3-e4e1-4966-9aeb-2bdb8d16cba7", - host: "127.0.0.1:10002", - "content-length": "6803" - } - } + batchRequest1Headers ); // we submitted the batch OK assert.strictEqual(request1Result.status, 202); - const request2Result = await axios.get( - `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + const request2Result = await getToAzurite( + `${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "7bbeb6b2-a1c7-4fed-8a3c-80f6b3e7db8c", - accept: "application/json;odata=minimalmetadata", - host: "127.0.0.1:10002" - } + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "7bbeb6b2-a1c7-4fed-8a3c-80f6b3e7db8c", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" } ); assert.strictEqual(request2Result.status, 200); - const request3Result = await axios.get( - `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + const request3Result = await getToAzurite( + `${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "41eb727e-1f85-4f53-b4e1-2df2628b2903", - accept: "application/json;odata=minimalmetadata", - host: "127.0.0.1:10002" - } + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "41eb727e-1f85-4f53-b4e1-2df2628b2903", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" } ); assert.strictEqual(request3Result.status, 200); @@ -120,49 +115,43 @@ describe("table Entity APIs test", () => { // prettier-ignore const batchRequest2RawRequestString: string = `--batch_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: multipart/mixed; boundary=changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\n\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPOST http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName} HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nPrefer: return-no-content\r\n\r\n{\"PartitionKey\":\"09CEE\",\"RowKey\":\"EA5F528CF1B84658A5CECC574848547B_FLOWVERSION-5539F65E020B44FCA32CF9CBE56E286A-08585830786980800821\",\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:47.4209193Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n{\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nPUT http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: W/\"datetime'2021-04-15T23%3A09%3A46.5910000Z'\"\r\n\r\n{\"Sku\":\"{\\\"name\\\":\\\"Standard\\\",\\\"plan\\\":{\\\"name\\\":\\\"farm0\\\",\\\"id\\\":\\\"/subscriptions/ea5f528c-f1b8-4658-a5ce-cc574848547b/resourcegroups/rgname/providers/microsoft.web/serverfarms/farm0\\\",\\\"type\\\":\\\"Microsoft.Web/ServerFarms\\\"}}\",\"State\":\"Enabled\",\"CreatedTime\":\"2021-04-15T23:09:46.5446473Z\",\"CreatedTime@odata.type\":\"Edm.DateTime\",\"ChangedTime\":\"2021-04-15T23:09:47.4214726Z\",\"ChangedTime@odata.type\":\"Edm.DateTime\",\"DeletedTime\":\"1970-01-01T00:00:00Z\",\"DeletedTime@odata.type\":\"Edm.DateTime\",\"ChangedOperationId\":\"f2503371-15c7-4314-9803-81ea69f1ca72\",\"FlowId\":\"5539f65e020b44fca32cf9cbe56e286a\",\"SubscriptionId\":\"ea5f528c-f1b8-4658-a5ce-cc574848547b\",\"ResourceGroupName\":\"de415c09-29bb-483d-9544-25602c1ff355\",\"FlowName\":\"testflow1\",\"FlowSequenceId\":\"08585830786980800821\",\"ScaleUnit\":\"CU03\",\"Location\":\"devfabric\",\"RuntimeConfiguration\":\"{}\",\"DefinitionCompressed\":\"jwcotS/9AEgVAwCiRhYYkLcNkP8mJJYMoNGjbJnZPa29JAj6mJmxrTE9/2R9ohB1/NkjGtPz5ue0veuIO/Bh4F5oChYGDVOK3MToeBoFf7AtSEKrwCZGxxFRXsjU9Y9ObxOj44BjAQEAHmQzCg==\",\"DefinitionCompressed@odata.type\":\"Edm.Binary\",\"Metadata\":\"F3t9\",\"Metadata@odata.type\":\"Edm.Binary\",\"ParametersCompressed\":\"F3t9\",\"ParametersCompressed@odata.type\":\"Edm.Binary\",\"ConnectionReferences\":\"F3t9\",\"ConnectionReferences@odata.type\":\"Edm.Binary\",\"WorkflowReferences\":\"F3t9\",\"WorkflowReferences@odata.type\":\"Edm.Binary\",\"KeyVaultCertificateReferences\":\"F3t9\",\"KeyVaultCertificateReferences@odata.type\":\"Edm.Binary\",\"RuntimeContext\":\"9wwotS/9AEjlAwByiBkYkMU5BL8arW5Jf8FNkkBfmOlff9ZsdxcWrTF0mx+8MGnqWiyshMHAwMidxtAJrOk2bmWAjRV8Ta7rVnzgkVCFZ7LZJJFlmzuNoTuuSiEhqMI7jaHb/GBF15nC6V6cLr66kv9NxwIGAL9DUfY8vlXeBHXArwqTKlQZ\",\"RuntimeContext@odata.type\":\"Edm.Binary\",\"FlowUpdatedTime\":\"2021-04-15T23:09:47.4101988Z\",\"FlowUpdatedTime@odata.type\":\"Edm.DateTime\"}\r\n--changeset_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n--batch_3e8c6583-146e-4326-835f-5f7321fc6711--\r\n`; - const request4Result = await axios.post( - `${protocol}://${host}:${port}/${accountName}/$batch`, + const request4Result = await postToAzurite( + `$batch`, batchRequest2RawRequestString, { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "f2503371-15c7-4314-9803-81ea69f1ca72", - accept: "application/json;odata=nometadata", - "content-type": - "multipart/mixed; boundary=batch_3e8c6583-146e-4326-835f-5f7321fc6711", - host: "127.0.0.1:10002", - "content-length": "6865" - } + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "f2503371-15c7-4314-9803-81ea69f1ca72", + accept: "application/json;odata=nometadata", + "content-type": + "multipart/mixed; boundary=batch_3e8c6583-146e-4326-835f-5f7321fc6711", + host: "127.0.0.1:10002", + "content-length": "6865" } ); // we submitted the batch OK assert.strictEqual(request4Result.status, 202); - const request5Result = await axios.get( - `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + const request5Result = await getToAzurite( + `${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "ceceedd3-4d7c-450f-a738-b83b21788d42", - accept: "application/json;odata=minimalmetadata", - host: "127.0.0.1:10002" - } + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "ceceedd3-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" } ); assert.strictEqual(request5Result.status, 200); - const request6Result = await axios.get( - `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + const request6Result = await getToAzurite( + `${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "ceceedd3-4d7c-450f-a738-b83b21788d42", - accept: "application/json;odata=minimalmetadata", - host: "127.0.0.1:10002" - } + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "ceceedd3-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" } ); assert.strictEqual(request6Result.status, 200); @@ -172,16 +161,14 @@ describe("table Entity APIs test", () => { // we need to look up EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1 // as this etag is also used with the delete in the failing batch request - const requestTestFlowResult = await axios.get( - `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1')`, + const requestTestFlowResult = await getToAzurite( + `${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1')`, { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "00000000-4d7c-450f-a738-b83b21788d42", - accept: "application/json;odata=minimalmetadata", - host: "127.0.0.1:10002" - } + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "00000000-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" } ); assert.strictEqual(requestTestFlowResult.status, 200); @@ -190,16 +177,14 @@ describe("table Entity APIs test", () => { const testFlowEtag: string = resultTestFlowData["odata.etag"]; // validate the etag that we are using to delete the flow - const validateEtagResult = await axios.get( - `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + const validateEtagResult = await getToAzurite( + `${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "00000001-4d7c-450f-a738-b83b21788d42", - accept: "application/json;odata=minimalmetadata", - host: "127.0.0.1:10002" - } + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "00000001-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" } ); assert.strictEqual(request6Result.status, 200); @@ -217,20 +202,18 @@ describe("table Entity APIs test", () => { // prettier-ignore const batchRequest3RawRequestString: string = `--batch_558d985f-491c-496d-b4a2-311c3e1e075d\r\nContent-Type: multipart/mixed; boundary=changeset_558d985f-491c-496d-b4a2-311c3e1e075d\r\n\r\n--changeset_558d985f-491c-496d-b4a2-311c3e1e075d\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nDELETE http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: ${flowEtag}\r\n\r\n--changeset_558d985f-491c-496d-b4a2-311c3e1e075d\r\nContent-Type: application/http\r\nContent-Transfer-Encoding: binary\r\n\r\nDELETE http://127.0.0.1:10002/devstoreaccount1/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWLOOKUP-DE415C09%3A2D29BB%3A2D483D%3A2D9544%3A2D25602C1FF355-TESTFLOW1') HTTP/1.1\r\nAccept: application/json;odata=nometadata\r\nContent-Type: application/json\r\nIf-Match: ${testFlowEtag}\r\n\r\n--changeset_558d985f-491c-496d-b4a2-311c3e1e075d--\r\n--batch_558d985f-491c-496d-b4a2-311c3e1e075d--\r\n`; - const request7Result = await axios.post( - `${protocol}://${host}:${port}/${accountName}/$batch`, + const request7Result = await postToAzurite( + `$batch`, batchRequest3RawRequestString, { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "41aef06f-9443-497e-b192-216ae988549b", - "content-type": - "multipart/mixed; boundary=batch_558d985f-491c-496d-b4a2-311c3e1e075d", - accept: "application/json;odata=nometadata", - host: "127.0.0.1:10002", - "content-length": "1120" - } + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "41aef06f-9443-497e-b192-216ae988549b", + "content-type": + "multipart/mixed; boundary=batch_558d985f-491c-496d-b4a2-311c3e1e075d", + accept: "application/json;odata=nometadata", + host: "127.0.0.1:10002", + "content-length": "1120" } ); // we submitted the batch OK @@ -238,21 +221,17 @@ describe("table Entity APIs test", () => { assert.strictEqual(request7Result.status, 202); // validate the object was deleted! - await axios - .get( - `${protocol}://${host}:${port}/${accountName}/${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, - { - headers: { - "user-agent": "ResourceStack/6.0.0.1260", - "x-ms-version": "2018-03-28", - "x-ms-client-request-id": "00000002-4d7c-450f-a738-b83b21788d42", - accept: "application/json;odata=minimalmetadata", - host: "127.0.0.1:10002" - } - } - ) - .catch((getErr) => { - assert.strictEqual(getErr.response.status, 404); - }); + await getToAzurite( + `${reproFlowsTableName}(PartitionKey='09CEE',RowKey='EA5F528CF1B84658A5CECC574848547B_FLOWIDENTIFIER-5539F65E020B44FCA32CF9CBE56E286A')`, + { + "user-agent": "ResourceStack/6.0.0.1260", + "x-ms-version": "2018-03-28", + "x-ms-client-request-id": "00000002-4d7c-450f-a738-b83b21788d42", + accept: "application/json;odata=minimalmetadata", + host: "127.0.0.1:10002" + } + ).catch((getErr) => { + assert.strictEqual(getErr.response.status, 404); + }); }); }); diff --git a/tests/table/apis/table.entity.tests.utils.for.rest.ts b/tests/table/apis/table.entity.tests.utils.for.rest.ts index b476a7322..266f5c0ab 100644 --- a/tests/table/apis/table.entity.tests.utils.for.rest.ts +++ b/tests/table/apis/table.entity.tests.utils.for.rest.ts @@ -1,21 +1,33 @@ -import { computeHMACSHA256 } from "../../../src/common/utils/utils"; +import { + computeHMACSHA256, + getURLQueries +} from "../../../src/common/utils/utils"; import { HeaderConstants } from "../../../src/table/utils/constants"; -import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME } from "../../testutils"; +import TableEntityTestConfig from "./table.entity.test.config"; -export const accountName = EMULATOR_ACCOUNT_NAME; -export const sharedKey = EMULATOR_ACCOUNT_KEY; -const key1 = Buffer.from(sharedKey, "base64"); -// need to create the shared key -// using SharedKeyLite as it is quick and easy -export function axiosRequestConfig(stringToSign: string) { +const key1 = Buffer.from(TableEntityTestConfig.sharedKey, "base64"); + +/** + * Creates the Axios request options using shared key lite + * Authorization header for Azurite table request + * + * @export + * @param {string} url + * * @param {string} path + * @param {*} headers + * @return {*} axios request options + */ +export function axiosRequestConfig( + url: string, + path: string, + headersIn: any +): any { + const stringToSign = createStringToSignForSharedKeyLite(url, path, headersIn); const signature1 = computeHMACSHA256(stringToSign, key1); - const authValue = `SharedKeyLite ${accountName}:${signature1}`; + const authValue = `SharedKeyLite ${TableEntityTestConfig.accountName}:${signature1}`; + const headers = Object.assign(headersIn, { Authorization: authValue }); return { - headers: { - "Content-Type": "application/json", - Accept: "application/json;odata=nometadata", - Authorization: authValue - } + headers }; } @@ -25,11 +37,13 @@ export function axiosRequestConfig(stringToSign: string) { * * @private * @param {string} url + * @param {string} path * @param {any} headers * @returns {string} */ -export function createSignatureForSharedKeyLite( +export function createStringToSignForSharedKeyLite( url: string, + path: string, headers: any ): string { const stringToSign: string = @@ -40,12 +54,13 @@ export function createSignatureForSharedKeyLite( "\n" + getCanonicalizedResourceString( url, - accountName, - "/devstoreaccount1/Tables" + TableEntityTestConfig.accountName, + `/${TableEntityTestConfig.accountName}/${path.replace(/'/g, "%27")}` ); return stringToSign; } + /** * Retrieve header value according to shared key sign rules. * @see https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-shared-key @@ -130,14 +145,3 @@ export function getCanonicalizedResourceString( function getPath(url: string): string { return url; } -/** - * Retrieves queries from URL. - * - * @private - * @param {string} url - * @returns {string} - */ -function getURLQueries(url: string): { [key: string]: string } { - const lowercaseQueries: { [key: string]: string } = {}; - return lowercaseQueries; -} From 8d73db224e95e1aea258ff10da15de8828d40273 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Tue, 20 Apr 2021 10:13:04 +0200 Subject: [PATCH 51/57] removed only call from entity test --- tests/table/apis/table.entity.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.test.ts index bbbef5e3b..b4f2be7a3 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.test.ts @@ -115,7 +115,7 @@ describe("table Entity APIs test", () => { }); // Insert entity property with type "Edm.DateTime", server will convert to UTC time - it.only("Insert new Entity property with type Edm.DateTime will convert to UTC, @loki", (done) => { + it("Insert new Entity property with type Edm.DateTime will convert to UTC, @loki", (done) => { const timeValue = "2012-01-02T23:00:00"; const entity = { PartitionKey: "part1", From 22cb0936baba72cfbda644ec8edbc4f0724c2996 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Tue, 20 Apr 2021 10:17:17 +0200 Subject: [PATCH 52/57] uupdated change log --- ChangeLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.md b/ChangeLog.md index a707f63f2..2ee784da0 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -12,6 +12,7 @@ Table: - Convert entity properties with type "Edm.DateTime" to UTC time, to be aligned with Azure server. - Support Batch API - Allow complex RowKey and PartitionKey in batch API +- Adds support for replaying requests logged in debug logging ## 2021.2 Version 3.11.0 From d78f20fd4819dfc9f287fdc0e7b249053fe7872d Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Tue, 20 Apr 2021 15:53:04 +0200 Subject: [PATCH 53/57] corrected based on Xiaoning's comments --- tests/table/apis/table.entity.tests.azure.data-tables.ts | 2 +- tests/table/apis/table.entity.tests.utils.for.rest.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/table/apis/table.entity.tests.azure.data-tables.ts b/tests/table/apis/table.entity.tests.azure.data-tables.ts index dbadb7a3e..d44779319 100644 --- a/tests/table/apis/table.entity.tests.azure.data-tables.ts +++ b/tests/table/apis/table.entity.tests.azure.data-tables.ts @@ -104,7 +104,7 @@ describe("table Entity APIs test", () => { }); // https://github.com/Azure/Azurite/issues/754 - it.only("Batch API should correctly process LogicApp style update request sequence", async () => { + it("Batch API should correctly process LogicApp style update request sequence", async () => { await tableClient.create(); const logicAppReproEntity = new LogicAppReproEntity(); const insertedEntityHeaders = await tableClient.createEntity< diff --git a/tests/table/apis/table.entity.tests.utils.for.rest.ts b/tests/table/apis/table.entity.tests.utils.for.rest.ts index 266f5c0ab..eb2f11f8e 100644 --- a/tests/table/apis/table.entity.tests.utils.for.rest.ts +++ b/tests/table/apis/table.entity.tests.utils.for.rest.ts @@ -13,7 +13,7 @@ const key1 = Buffer.from(TableEntityTestConfig.sharedKey, "base64"); * * @export * @param {string} url - * * @param {string} path + * @param {string} path * @param {*} headers * @return {*} axios request options */ From d7842d5474e9599a6de203c1f34c2a4cd8a3bc37 Mon Sep 17 00:00:00 2001 From: Edwin Huber Date: Tue, 27 Apr 2021 11:56:27 +0200 Subject: [PATCH 54/57] Table batch error handling (#763) * added serialization of errors and refactored some tests and serialization logic * tidied up the serialization logic and ensured that we skip request content on over 100 entries * some final updates before PR * corrected pathing of StorageError in table serialization file * clean up * corrected serialization and added Bad Request string to HTTP Status code serializer --- src/table/batch/TableBatchOrchestrator.ts | 43 ++++- src/table/batch/TableBatchSerialization.ts | 154 ++++++++++++++---- tests/table/apis/AzureDataTablesTestEntity.ts | 34 ++++ tests/table/apis/TestEntity.ts | 21 +++ .../apis/table-batch-api-error-handling.md | 39 +++++ .../apis/table.batch.tests.errorhandling.ts | 96 +++++++++++ tests/table/apis/table.entity.test.utils.ts | 86 ++++++++++ .../table.entity.tests.azure.data-tables.ts | 74 ++------- ...e.entity.test.ts => table.entity.tests.ts} | 73 ++------- tests/table/apis/table.test.ts | 47 +++--- 10 files changed, 484 insertions(+), 183 deletions(-) create mode 100644 tests/table/apis/AzureDataTablesTestEntity.ts create mode 100644 tests/table/apis/TestEntity.ts create mode 100644 tests/table/apis/table-batch-api-error-handling.md create mode 100644 tests/table/apis/table.batch.tests.errorhandling.ts create mode 100644 tests/table/apis/table.entity.test.utils.ts rename tests/table/apis/{table.entity.test.ts => table.entity.tests.ts} (95%) diff --git a/src/table/batch/TableBatchOrchestrator.ts b/src/table/batch/TableBatchOrchestrator.ts index f0b451cfa..4b3e61e13 100644 --- a/src/table/batch/TableBatchOrchestrator.ts +++ b/src/table/batch/TableBatchOrchestrator.ts @@ -33,6 +33,8 @@ export default class TableBatchOrchestrator { private serialization = new TableBatchSerialization(); private context: TableStorageContext; private parentHandler: TableHandler; + private wasError: boolean = false; + private errorResponse: string = ""; public constructor(context: TableStorageContext, handler: TableHandler) { this.context = context; @@ -53,9 +55,15 @@ export default class TableBatchOrchestrator { this.batchOperations = this.serialization.deserializeBatchRequest( batchRequestBody ); - - await this.submitRequestsToHandlers(); - + if (this.batchOperations.length > 100) { + this.wasError = true; + this.errorResponse = this.serialization.serializeGeneralRequestError( + "0:The batch request operation exceeds the maximum 100 changes per change set.", + this.context.xMsRequestID + ); + } else { + await this.submitRequestsToHandlers(); + } return this.serializeResponses(); } @@ -73,7 +81,7 @@ export default class TableBatchOrchestrator { this.requests.push(request); }); - let contentID = 1; // contentID starts at 1 for batch + let contentID = 1; // ToDO: validate contentID starts at 1 for batch if (this.requests.length > 0) { for (const singleReq of this.requests) { try { @@ -83,7 +91,15 @@ export default class TableBatchOrchestrator { contentID ); } catch (err) { - throw err; + this.wasError = true; + this.errorResponse = this.serialization.serializeError( + err, + contentID, + singleReq + ); + // ToDo: need to reset changes until now + // then break out of loop and serilaize error + break; } contentID++; } @@ -119,11 +135,20 @@ export default class TableBatchOrchestrator { responseString += "Content-Type: multipart/mixed; boundary=" + changesetBoundary + "\r\n"; changesetBoundary = "\r\n--" + changesetBoundary; - this.requests.forEach((request) => { + if (this.wasError === false) { + this.requests.forEach((request) => { + responseString += changesetBoundary; + responseString += request.response; + responseString += "\r\n\r\n"; + }); + } else { + // serialize the error responseString += changesetBoundary; - responseString += request.response; - responseString += "\r\n\r\n"; - }); + // then headers + // content type etc + // then HTTP/1.1 404 etc + responseString += this.errorResponse; + } responseString += changesetBoundary + "--\r\n"; responseString += batchBoundary + "--\r\n"; return responseString; diff --git a/src/table/batch/TableBatchSerialization.ts b/src/table/batch/TableBatchSerialization.ts index 0e4de687c..ab84dfda7 100644 --- a/src/table/batch/TableBatchSerialization.ts +++ b/src/table/batch/TableBatchSerialization.ts @@ -1,4 +1,3 @@ -import { StorageError } from "../../blob/generated/artifacts/mappers"; // import BatchOperation from "../../common/BatchOperation"; // import { BatchOperationType } from "../../common/BatchOperation"; import { BatchType } from "../../common/batch/BatchOperation"; @@ -10,6 +9,8 @@ import { BatchSerialization } from "../../common/batch/BatchSerialization"; import TableBatchOperation from "../batch/TableBatchOperation"; import * as Models from "../generated/artifacts/models"; import TableBatchUtils from "./TableBatchUtils"; +import StorageError from "../errors/StorageError"; +import { truncatedISO8061Date } from "../../common/utils/utils"; /** * The semantics for entity group transactions are defined by the OData Protocol Specification. @@ -157,7 +158,7 @@ export class TableBatchSerialization extends BatchSerialization { serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); serializedResponses = this.serializeHttpStatusCode( serializedResponses, - response + response.statusCode ); // ToDo: Correct the handling of Content-ID if (request.contentID !== undefined) { @@ -165,7 +166,7 @@ export class TableBatchSerialization extends BatchSerialization { "Content-ID: " + request.contentID.toString() + "\r\n"; } - serializedResponses = this.AddNoSniffNoCache(serializedResponses); + serializedResponses = this.SerializeNoSniffNoCache(serializedResponses); serializedResponses = this.serializePreferenceApplied( request, @@ -173,8 +174,8 @@ export class TableBatchSerialization extends BatchSerialization { ); serializedResponses = this.serializeDataServiceVersion( - request, - serializedResponses + serializedResponses, + request ); serializedResponses += @@ -208,13 +209,13 @@ export class TableBatchSerialization extends BatchSerialization { serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); serializedResponses = this.serializeHttpStatusCode( serializedResponses, - response + response.statusCode ); - serializedResponses = this.AddNoSniffNoCache(serializedResponses); + serializedResponses = this.SerializeNoSniffNoCache(serializedResponses); serializedResponses = this.serializeDataServiceVersion( - request, - serializedResponses + serializedResponses, + request ); return serializedResponses; @@ -237,7 +238,7 @@ export class TableBatchSerialization extends BatchSerialization { serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); serializedResponses = this.serializeHttpStatusCode( serializedResponses, - response + response.statusCode ); // ToDo_: Correct the handling of content-ID if (request.contentID) { @@ -245,7 +246,7 @@ export class TableBatchSerialization extends BatchSerialization { "Content-ID: " + request.contentID.toString() + "\r\n"; } - serializedResponses = this.AddNoSniffNoCache(serializedResponses); + serializedResponses = this.SerializeNoSniffNoCache(serializedResponses); serializedResponses = this.serializePreferenceApplied( request, @@ -253,8 +254,8 @@ export class TableBatchSerialization extends BatchSerialization { ); serializedResponses = this.serializeDataServiceVersion( - request, - serializedResponses + serializedResponses, + request ); if (null !== response.eTag && undefined !== response.eTag) { @@ -301,9 +302,9 @@ export class TableBatchSerialization extends BatchSerialization { serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); serializedResponses = this.serializeHttpStatusCode( serializedResponses, - response + response.statusCode ); - serializedResponses = this.AddNoSniffNoCache(serializedResponses); + serializedResponses = this.SerializeNoSniffNoCache(serializedResponses); // ToDo_: Correct the handling of content-ID if (request.contentID) { serializedResponses += @@ -312,8 +313,8 @@ export class TableBatchSerialization extends BatchSerialization { // ToDo: not sure about other headers like cache control etc right now // Service defaults to v1.0 serializedResponses = this.serializeDataServiceVersion( - request, - serializedResponses + serializedResponses, + request ); if (null !== response.eTag && undefined !== response.eTag) { @@ -339,19 +340,19 @@ export class TableBatchSerialization extends BatchSerialization { serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); serializedResponses = this.serializeHttpStatusCode( serializedResponses, - response + response.statusCode ); serializedResponses = this.serializeDataServiceVersion( - request, - serializedResponses + serializedResponses, + request ); serializedResponses += "Content-Type: "; serializedResponses += request.params.queryOptions?.format; serializedResponses += ";streaming=true;charset=utf-8\r\n"; // getting this from service, so adding here as well - serializedResponses = this.AddNoSniffNoCache(serializedResponses); + serializedResponses = this.SerializeNoSniffNoCache(serializedResponses); if (response.eTag) { serializedResponses += "ETag: " + response.eTag; @@ -391,12 +392,12 @@ export class TableBatchSerialization extends BatchSerialization { serializedResponses = this.SetContentTypeAndEncoding(serializedResponses); serializedResponses = this.serializeHttpStatusCode( serializedResponses, - response + response.statusCode ); serializedResponses = this.serializeDataServiceVersion( - request, - serializedResponses + serializedResponses, + request ); serializedResponses += "Content-Type: "; @@ -405,7 +406,7 @@ export class TableBatchSerialization extends BatchSerialization { // Azure Table service defaults to this in the response // X-Content-Type-Options: nosniff\r\n - serializedResponses = this.AddNoSniffNoCache(serializedResponses); + serializedResponses = this.SerializeNoSniffNoCache(serializedResponses); serializedResponses += "\r\n"; @@ -450,12 +451,18 @@ export class TableBatchSerialization extends BatchSerialization { * @return {*} * @memberof TableBatchSerialization */ - private AddNoSniffNoCache(serializedResponses: string) { - serializedResponses += "X-Content-Type-Options: nosniff\r\n"; + private SerializeNoSniffNoCache(serializedResponses: string) { + serializedResponses = this.SerializeXContentTypeOptions( + serializedResponses + ); serializedResponses += "Cache-Control: no-cache\r\n"; return serializedResponses; } + private SerializeXContentTypeOptions(serializedResponses: string) { + serializedResponses += "X-Content-Type-Options: nosniff\r\n"; + return serializedResponses; + } /** * Serializes the HTTP response * ToDo: Need to check where we have implemented this elsewhere and see if we can reuse @@ -475,6 +482,8 @@ export class TableBatchSerialization extends BatchSerialization { return "No Content"; case 404: return "Not Found"; + case 400: + return "Bad Request"; default: return "STATUS_CODE_NOT_IMPLEMENTED"; } @@ -509,12 +518,15 @@ export class TableBatchSerialization extends BatchSerialization { * @return {*} * @memberof TableBatchSerialization */ - private serializeHttpStatusCode(serializedResponses: string, response: any) { + private serializeHttpStatusCode( + serializedResponses: string, + statusCode: number + ) { serializedResponses += "HTTP/1.1 " + - response.statusCode.toString() + + statusCode.toString() + " " + - this.GetStatusMessageString(response.statusCode) + + this.GetStatusMessageString(statusCode) + "\r\n"; return serializedResponses; } @@ -563,13 +575,89 @@ export class TableBatchSerialization extends BatchSerialization { * @memberof TableBatchSerialization */ private serializeDataServiceVersion( - request: BatchRequest, - serializedResponses: string + serializedResponses: string, + request: BatchRequest | undefined ) { - if (undefined !== request.params && request.params.dataServiceVersion) { + if ( + undefined !== request && + undefined !== request.params && + request.params.dataServiceVersion + ) { serializedResponses += "DataServiceVersion: " + request.params.dataServiceVersion + ";\r\n"; + } else { + // default to 3.0 + serializedResponses += "DataServiceVersion: 3.0;\r\n"; } return serializedResponses; } + + /** + * Serializes an error generated during batch processing + * https://docs.microsoft.com/en-us/rest/api/storageservices/performing-entity-group-transactions#sample-error-response + * @private + * @param {*} err + * @return {*} {string} + * @memberof TableBatchSerialization + */ + public serializeError( + err: any, + contentID: number, + request: BatchRequest + ): string { + const changesetBoundary = this.changesetBoundary.replace( + "changeset", + "changesetresponse" + ); + let errorReponse = ""; + const odataError = err as StorageError; + errorReponse += changesetBoundary + "\r\n"; + // Errors in batch processing generate Bad Request error + errorReponse = this.serializeHttpStatusCode(errorReponse, 400); + errorReponse += "Content-ID: " + contentID + "\r\n"; + errorReponse = this.serializeDataServiceVersion(errorReponse, request); + // ToDo: Check if we need to observe other odata formats for errors + errorReponse += + "Content-Type: application/json;odata=minimalmetadata;charset=utf-8\r\n"; + errorReponse += "\r\n"; + errorReponse += odataError.body + "\r\n"; + return errorReponse; + } + + /** + * Serializes top level errors not generated from individual request processing + * + * @param {string} odataErrorString + * @param {(string | undefined)} requestId + * @return {*} {string} + * @memberof TableBatchSerialization + */ + public serializeGeneralRequestError( + odataErrorString: string, + requestId: string | undefined + ): string { + const changesetBoundary = this.changesetBoundary.replace( + "changeset", + "changesetresponse" + ); + let errorReponse = ""; + + errorReponse += changesetBoundary + "\r\n"; + // Errors in batch processing generate Bad Request error + errorReponse = this.serializeHttpStatusCode(errorReponse, 400); + errorReponse = this.SerializeXContentTypeOptions(errorReponse); + errorReponse = this.serializeDataServiceVersion(errorReponse, undefined); + // ToDo: Serialize Content type etc + errorReponse += + "Content-Type: application/json;odata=minimalmetadata;charset=utf-8\r\n"; + errorReponse += "\r\n"; + let requestIdResponseString = ""; + if (requestId !== undefined) { + requestIdResponseString = `RequestId:${requestId}\\n`; + } + // 2021-04-23T12:40:31.4944778 + const date = truncatedISO8061Date(new Date(), true); + errorReponse += `{\"odata.error\":{\"code\":\"InvalidInput\",\"message\":{\"lang\":\"en-US\",\"value\":\"${odataErrorString}\\n${requestIdResponseString}Time:${date}\"}}}\r\n`; + return errorReponse; + } } diff --git a/tests/table/apis/AzureDataTablesTestEntity.ts b/tests/table/apis/AzureDataTablesTestEntity.ts new file mode 100644 index 000000000..47d66d6fe --- /dev/null +++ b/tests/table/apis/AzureDataTablesTestEntity.ts @@ -0,0 +1,34 @@ +import { getUniqueName } from "../../testutils"; + +/** + * Creates an entity for tests, with a randomized row key, + * to avoid conflicts on inserts. + * + * @return {*} {TestEntity} + */ +export function createBasicEntityForTest( + partitionKey: string +): AzureDataTablesTestEntity { + return new AzureDataTablesTestEntity( + partitionKey, + getUniqueName("row"), + "value1" + ); +} + +/** + * This is the Entity Class used by Azure Data-Tables SDK tests + * + * @export + * @class AzureDataTablesTestEntity + */ +export class AzureDataTablesTestEntity { + public partitionKey: string; + public rowKey: string; + public myValue: string; + constructor(part: string, row: string, value: string) { + this.partitionKey = part; + this.rowKey = row; + this.myValue = value; + } +} diff --git a/tests/table/apis/TestEntity.ts b/tests/table/apis/TestEntity.ts new file mode 100644 index 000000000..156406241 --- /dev/null +++ b/tests/table/apis/TestEntity.ts @@ -0,0 +1,21 @@ +import * as Azure from "azure-storage"; +const eg = Azure.TableUtilities.entityGenerator; + +/** + * Provides the default entity we use for Table tests + * + * @export + * @class TestEntity + */ +export class TestEntity { + public PartitionKey: Azure.TableUtilities.entityGenerator.EntityProperty< + string + >; + public RowKey: Azure.TableUtilities.entityGenerator.EntityProperty; + public myValue: Azure.TableUtilities.entityGenerator.EntityProperty; + constructor(part: string, row: string, value: string) { + this.PartitionKey = eg.String(part); + this.RowKey = eg.String(row); + this.myValue = eg.String(value); + } +} diff --git a/tests/table/apis/table-batch-api-error-handling.md b/tests/table/apis/table-batch-api-error-handling.md new file mode 100644 index 000000000..c2151d1a5 --- /dev/null +++ b/tests/table/apis/table-batch-api-error-handling.md @@ -0,0 +1,39 @@ +# Table Batch API Error Handling + +## Overview + +Each feature or check will be covered by a test case. +Each test case will be validated against the service. +The test case against service will be used to validate and set response correctly where not clearly documented for the REST API. + +See also: +https://docs.microsoft.com/en-us/rest/api/storageservices/performing-entity-group-transactions#sample-error-response + +## Details + +The following list of features and behavior will serve as a checklist for testing Azurite Batch API error handling: + +### Done: + +- When a batch request fails, if the failure is during individual batch item processing, the response must be serialized as a batch response to the client. +- When an individual operation fails, the response for the change set indicates status code 400 (Bad Request). + - Additional error information within the response indicates which operation failed by returning the index of that operation. + - The index is the sequence number of the command in the payload via the Content-ID. +- A batch can include at most 100 entities. +- Operations are processed in the order they are specified in the change set. +- The Table service does not support linking operations in a change set. + -- is this a reference to content-id processing logic (done, as we don't support content id references) +- the batch request returns status code 202 (Accepted), even if one of the operations in the change set fails. +- If the batch request itself fails, it fails before any operation in the change set is executed. (done for max operations, other cases will be addressed as they come up) + +### ToDo: + +- Check if we need to observe other odata formats for errors +- All entities in a batch must have the same PartitionKey value. +- An entity can appear only once in a batch, and only one operation may be performed against it. + - Requires that we check both partition key and row key (as an entity key is made up of both) +- its total payload may be no more than 4 MiB in size. +- There should only be a single change set within a batch. + --> If a batch includes more than one change set, the first change set will be processed by the service, and additional change sets will be rejected with status code 400 (Bad Request). +- A Query must be a single operation in its batch. +- all operations in the change set either succeed or fail. diff --git a/tests/table/apis/table.batch.tests.errorhandling.ts b/tests/table/apis/table.batch.tests.errorhandling.ts new file mode 100644 index 000000000..828f808c9 --- /dev/null +++ b/tests/table/apis/table.batch.tests.errorhandling.ts @@ -0,0 +1,96 @@ +// Tests in this file are using @azure/data-tables + +import * as assert from "assert"; +import { TableClient, TablesSharedKeyCredential } from "@azure/data-tables"; +import { configLogger } from "../../../src/common/Logger"; +import TableServer from "../../../src/table/TableServer"; +import { + EMULATOR_ACCOUNT_KEY, + EMULATOR_ACCOUNT_NAME, + getUniqueName +} from "../../testutils"; +import { + AzureDataTablesTestEntity, + createBasicEntityForTest +} from "./AzureDataTablesTestEntity"; +import { + createTableServerForTestHttps, + createUniquePartitionKey, + HOST, + PORT +} from "./table.entity.test.utils"; + +// Set true to enable debug log +configLogger(false); + +describe("table Entity APIs test", () => { + let server: TableServer; + + const requestOverride = { headers: {} }; + + before(async () => { + server = createTableServerForTestHttps(); + await server.start(); + requestOverride.headers = { + Prefer: "return-content", + accept: "application/json;odata=fullmetadata" + }; + }); + + after(async () => { + await server.close(); + }); + + it("Batch API should serialize errors according to group transaction spec, @loki", async () => { + const partitionKey = createUniquePartitionKey(); + const testEntities: AzureDataTablesTestEntity[] = [ + createBasicEntityForTest(partitionKey), + createBasicEntityForTest(partitionKey), + createBasicEntityForTest(partitionKey) + ]; + + const badTableClient = new TableClient( + `https://${HOST}:${PORT}/${EMULATOR_ACCOUNT_NAME}`, + "noExistingTable", + new TablesSharedKeyCredential(EMULATOR_ACCOUNT_NAME, EMULATOR_ACCOUNT_KEY) + ); + + // await badTableClient.create(); // deliberately do not create table + const batch = badTableClient.createBatch(partitionKey); + batch.createEntities(testEntities); + + try { + await batch.submitBatch(); + } catch (err) { + assert.strictEqual(err.statusCode, 400); + assert.strictEqual(err.code, "TableNotFound"); + } + }); + + it("Batch API should reject request with more than 100 transactions, @loki", async () => { + const partitionKey = createUniquePartitionKey(); + const tableName: string = getUniqueName("datatables"); + const testEntities: AzureDataTablesTestEntity[] = []; + const TOO_MANY_REQUESTS = 101; + while (testEntities.length < TOO_MANY_REQUESTS) { + testEntities.push(createBasicEntityForTest(partitionKey)); + } + + const tooManyRequestsClient = new TableClient( + `https://${HOST}:${PORT}/${EMULATOR_ACCOUNT_NAME}`, + tableName, + new TablesSharedKeyCredential(EMULATOR_ACCOUNT_NAME, EMULATOR_ACCOUNT_KEY) + ); + + await tooManyRequestsClient.create(); + const batch = tooManyRequestsClient.createBatch(partitionKey); + batch.createEntities(testEntities); + + try { + await batch.submitBatch(); + } catch (err) { + assert.strictEqual(err.statusCode, 400); + assert.strictEqual(err.code, "InvalidInput"); + } + }); +}); diff --git a/tests/table/apis/table.entity.test.utils.ts b/tests/table/apis/table.entity.test.utils.ts new file mode 100644 index 000000000..8a513972f --- /dev/null +++ b/tests/table/apis/table.entity.test.utils.ts @@ -0,0 +1,86 @@ +import { + EMULATOR_ACCOUNT_KEY, + EMULATOR_ACCOUNT_NAME, + getUniqueName +} from "../../testutils"; +import { TestEntity } from "./TestEntity"; +import TableServer from "../../../src/table/TableServer"; +import TableConfiguration from "../../../src/table/TableConfiguration"; + +export const PROTOCOL = "http"; +export const HOST = "127.0.0.1"; +export const PORT = 11002; +const metadataDbPath = "__tableTestsStorage__"; +const enableDebugLog: boolean = false; +const debugLogPath: string = "g:/debug.log"; +const connectionString = + `DefaultEndpointsProtocol=${PROTOCOL};AccountName=${EMULATOR_ACCOUNT_NAME};` + + `AccountKey=${EMULATOR_ACCOUNT_KEY};TableEndpoint=${PROTOCOL}://${HOST}:${PORT}/${EMULATOR_ACCOUNT_NAME};`; + +const config = new TableConfiguration( + HOST, + PORT, + metadataDbPath, + enableDebugLog, + false, + undefined, + debugLogPath +); + +const httpsConfig = new TableConfiguration( + HOST, + PORT, + metadataDbPath, + enableDebugLog, + false, + undefined, + debugLogPath, + false, + true, + "tests/server.cert", + "tests/server.key" +); + +/** + * Creates an entity for tests, with a randomized row key, + * to avoid conflicts on inserts. + * + * @return {*} {TestEntity} + */ +export function createBasicEntityForTest(): TestEntity { + return new TestEntity("part1", getUniqueName("row"), "value1"); +} + +/** + * Creates the Azurite TableServer used in Table API tests + * + * @export + * @return {*} {TableServer} + */ +export function createTableServerForTest(): TableServer { + return new TableServer(config); +} + +export function createTableServerForTestHttps(): TableServer { + return new TableServer(httpsConfig); +} + +/** + * Provides the connection string to connect to the Azurite table server + * + * @export + * @return {*} {string} + */ +export function createConnectionStringForTest(): string { + return connectionString; +} + +/** + * return a unique parition key for data-tables tests + * + * @export + * @return {*} {string} + */ +export function createUniquePartitionKey(): string { + return getUniqueName("datatablestests"); +} diff --git a/tests/table/apis/table.entity.tests.azure.data-tables.ts b/tests/table/apis/table.entity.tests.azure.data-tables.ts index d44779319..5fcee8773 100644 --- a/tests/table/apis/table.entity.tests.azure.data-tables.ts +++ b/tests/table/apis/table.entity.tests.azure.data-tables.ts @@ -4,79 +4,40 @@ import * as assert from "assert"; import LogicAppReproEntity from "./table.entity.test.logicapp.entity"; import { TableClient, TablesSharedKeyCredential } from "@azure/data-tables"; import { configLogger } from "../../../src/common/Logger"; -import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; import { EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME, getUniqueName } from "../../testutils"; +import { + AzureDataTablesTestEntity, + createBasicEntityForTest +} from "./AzureDataTablesTestEntity"; +import { + createTableServerForTestHttps, + createUniquePartitionKey, + HOST, + PORT +} from "./table.entity.test.utils"; // Set true to enable debug log configLogger(false); -const partitionKeyForDataTablesTests: string = getUniqueName("datatablestests"); -/** - * Creates an entity for tests, with a randomized row key, - * to avoid conflicts on inserts. - * - * @return {*} {TestEntity} - */ -function createBasicEntityForTest(): AzureDataTablesTestEntity { - return new AzureDataTablesTestEntity( - partitionKeyForDataTablesTests, - getUniqueName("row"), - "value1" - ); -} - -class AzureDataTablesTestEntity { - public partitionKey: string; - public rowKey: string; - public myValue: string; - constructor(part: string, row: string, value: string) { - this.partitionKey = part; - this.rowKey = row; - this.myValue = value; - } -} describe("table Entity APIs test", () => { - // TODO: Create a server factory as tests utils - const protocol = "https"; - const host = "127.0.0.1"; - const port = 11002; - const metadataDbPath = "__tableTestsStorage__"; - const enableDebugLog: boolean = true; - const debugLogPath: string = "g:/debug.log"; - const config = new TableConfiguration( - host, - port, - metadataDbPath, - enableDebugLog, - false, - undefined, - debugLogPath, - false, - true, - "tests/server.cert", - "tests/server.key" - ); - let server: TableServer; - const accountName = EMULATOR_ACCOUNT_NAME; - const sharedKey = EMULATOR_ACCOUNT_KEY; const tableName: string = getUniqueName("datatables"); const tableClient = new TableClient( - `${protocol}://${host}:${port}/${accountName}`, + `https://${HOST}:${PORT}/${EMULATOR_ACCOUNT_NAME}`, tableName, - new TablesSharedKeyCredential(accountName, sharedKey) + new TablesSharedKeyCredential(EMULATOR_ACCOUNT_NAME, EMULATOR_ACCOUNT_KEY) ); const requestOverride = { headers: {} }; before(async () => { - server = new TableServer(config); + server = createTableServerForTestHttps(); await server.start(); requestOverride.headers = { Prefer: "return-content", @@ -89,14 +50,15 @@ describe("table Entity APIs test", () => { }); it("Batch API should return row keys in format understood by @azure/data-tables, @loki", async () => { + const partitionKey = createUniquePartitionKey(); const testEntities: AzureDataTablesTestEntity[] = [ - createBasicEntityForTest(), - createBasicEntityForTest(), - createBasicEntityForTest() + createBasicEntityForTest(partitionKey), + createBasicEntityForTest(partitionKey), + createBasicEntityForTest(partitionKey) ]; await tableClient.create(); - const batch = tableClient.createBatch(partitionKeyForDataTablesTests); + const batch = tableClient.createBatch(partitionKey); await batch.createEntities(testEntities); const result = await batch.submitBatch(); assert.ok(result.subResponses[0].rowKey); diff --git a/tests/table/apis/table.entity.test.ts b/tests/table/apis/table.entity.tests.ts similarity index 95% rename from tests/table/apis/table.entity.test.ts rename to tests/table/apis/table.entity.tests.ts index b4f2be7a3..504e01244 100644 --- a/tests/table/apis/table.entity.test.ts +++ b/tests/table/apis/table.entity.tests.ts @@ -3,70 +3,29 @@ import * as Azure from "azure-storage"; import { configLogger } from "../../../src/common/Logger"; import StorageError from "../../../src/table/errors/StorageError"; -import TableConfiguration from "../../../src/table/TableConfiguration"; + import TableServer from "../../../src/table/TableServer"; import { - EMULATOR_ACCOUNT_KEY, - EMULATOR_ACCOUNT_NAME, getUniqueName, overrideRequest, restoreBuildRequestOptions } from "../../testutils"; +import { + createBasicEntityForTest, + createConnectionStringForTest, + createTableServerForTest +} from "./table.entity.test.utils"; +import { TestEntity } from "./TestEntity"; // Set true to enable debug log configLogger(false); -/** - * Creates an entity for tests, with a randomized row key, - * to avoid conflicts on inserts. - * - * @return {*} {TestEntity} - */ -function createBasicEntityForTest(): TestEntity { - return new TestEntity("part1", getUniqueName("row"), "value1"); -} - -class TestEntity { - public PartitionKey: Azure.TableUtilities.entityGenerator.EntityProperty< - string - >; - public RowKey: Azure.TableUtilities.entityGenerator.EntityProperty; - public myValue: Azure.TableUtilities.entityGenerator.EntityProperty; - constructor(part: string, row: string, value: string) { - this.PartitionKey = eg.String(part); - this.RowKey = eg.String(row); - this.myValue = eg.String(value); - } -} - -const eg = Azure.TableUtilities.entityGenerator; - describe("table Entity APIs test", () => { - // TODO: Create a server factory as tests utils - const protocol = "http"; - const host = "127.0.0.1"; - const port = 11002; - const metadataDbPath = "__tableTestsStorage__"; - const enableDebugLog: boolean = true; - const debugLogPath: string = "g:/debug.log"; - const config = new TableConfiguration( - host, - port, - metadataDbPath, - enableDebugLog, - false, - undefined, - debugLogPath - ); - let server: TableServer; - const accountName = EMULATOR_ACCOUNT_NAME; - const sharedKey = EMULATOR_ACCOUNT_KEY; - const connectionString = - `DefaultEndpointsProtocol=${protocol};AccountName=${accountName};` + - `AccountKey=${sharedKey};TableEndpoint=${protocol}://${host}:${port}/${accountName};`; - const tableService = Azure.createTableService(connectionString); + const tableService = Azure.createTableService( + createConnectionStringForTest() + ); // ToDo: added due to problem with batch responses not finishing properly - Need to investigate batch response tableService.enableGlobalHttpAgent = true; @@ -76,7 +35,7 @@ describe("table Entity APIs test", () => { before(async () => { overrideRequest(requestOverride, tableService); - server = new TableServer(config); + server = createTableServerForTest(); tableName = getUniqueName("table"); await server.start(); requestOverride.headers = { @@ -134,9 +93,9 @@ describe("table Entity APIs test", () => { "part1", "utctest", (error, result) => { - const entity: TestEntity = result; + const insertedEntity: TestEntity = result; assert.strictEqual( - entity.myValue._.toString(), + insertedEntity.myValue._.toString(), new Date(timeValue + "Z").toString() ); done(); @@ -181,15 +140,15 @@ describe("table Entity APIs test", () => { entityInsert, (insertError, insertResult, insertResponse) => { if (!insertError) { - var query = new Azure.TableQuery() + const query = new Azure.TableQuery() .where("PartitionKey == ?", "part2") .and("myValue == ?", "value1"); tableService.queryEntities( tableName, query, - null, - null, + null as any, + null as any, (queryError, queryResult, queryResponse) => { if (!queryError) { if (queryResult.entries && queryResult.entries.length > 0) { diff --git a/tests/table/apis/table.test.ts b/tests/table/apis/table.test.ts index 243f093d9..623bd6a14 100644 --- a/tests/table/apis/table.test.ts +++ b/tests/table/apis/table.test.ts @@ -2,46 +2,34 @@ import * as assert from "assert"; import * as Azure from "azure-storage"; import { configLogger } from "../../../src/common/Logger"; -import TableConfiguration from "../../../src/table/TableConfiguration"; import TableServer from "../../../src/table/TableServer"; import { HeaderConstants, TABLE_API_VERSION } from "../../../src/table/utils/constants"; import { - EMULATOR_ACCOUNT_KEY, EMULATOR_ACCOUNT_NAME, getUniqueName, overrideRequest, restoreBuildRequestOptions } from "../../testutils"; +import { + HOST, + PROTOCOL, + PORT, + createConnectionStringForTest, + createTableServerForTest +} from "./table.entity.test.utils"; // Set true to enable debug log configLogger(false); describe("table APIs test", () => { - // TODO: Create a server factory as tests utils - const protocol = "http"; - const host = "127.0.0.1"; - const port = 11002; - const metadataDbPath = "__tableTestsStorage__"; - - const config = new TableConfiguration( - host, - port, - metadataDbPath, - false, - false - ); - let server: TableServer; - const accountName = EMULATOR_ACCOUNT_NAME; - const sharedKey = EMULATOR_ACCOUNT_KEY; - const connectionString = - `DefaultEndpointsProtocol=${protocol};AccountName=${accountName};` + - `AccountKey=${sharedKey};TableEndpoint=${protocol}://${host}:${port}/${accountName};`; - const tableService = Azure.createTableService(connectionString); + const tableService = Azure.createTableService( + createConnectionStringForTest() + ); let tableName: string = getUniqueName("table"); @@ -49,7 +37,7 @@ describe("table APIs test", () => { before(async () => { overrideRequest(requestOverride, tableService); - server = new TableServer(config); + server = createTableServerForTest(); tableName = getUniqueName("table"); await server.start(); }); @@ -103,14 +91,17 @@ describe("table APIs test", () => { assert.equal(headers["x-ms-version"], TABLE_API_VERSION); const bodies = response.body! as any; assert.deepStrictEqual(bodies.TableName, tableName); - assert.deepStrictEqual(bodies["odata.type"], `${accountName}.Tables`); + assert.deepStrictEqual( + bodies["odata.type"], + `${EMULATOR_ACCOUNT_NAME}.Tables` + ); assert.deepStrictEqual( bodies["odata.metadata"], - `${protocol}://${host}:${port}/${accountName}/$metadata#Tables/@Element` + `${PROTOCOL}://${HOST}:${PORT}/${EMULATOR_ACCOUNT_NAME}/$metadata#Tables/@Element` ); assert.deepStrictEqual( bodies["odata.id"], - `${protocol}://${host}:${port}/${accountName}/Tables(${tableName})` + `${PROTOCOL}://${HOST}:${PORT}/${EMULATOR_ACCOUNT_NAME}/Tables(${tableName})` ); assert.deepStrictEqual( bodies["odata.editLink"], @@ -154,7 +145,7 @@ describe("table APIs test", () => { const bodies = response.body! as any; assert.deepStrictEqual( bodies["odata.metadata"], - `${protocol}://${host}:${port}/${accountName}/$metadata#Tables` + `${PROTOCOL}://${HOST}:${PORT}/${EMULATOR_ACCOUNT_NAME}/$metadata#Tables` ); assert.ok(bodies.value[0].TableName); assert.ok(bodies.value[0]["odata.type"]); @@ -185,7 +176,7 @@ describe("table APIs test", () => { const bodies = response.body! as any; assert.deepStrictEqual( bodies["odata.metadata"], - `${protocol}://${host}:${port}/${accountName}/$metadata#Tables` + `${PROTOCOL}://${HOST}:${PORT}/${EMULATOR_ACCOUNT_NAME}/$metadata#Tables` ); assert.ok(bodies.value[0].TableName); } From 73603d186fed5adac1097764676726c08f136b01 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Fri, 30 Apr 2021 03:53:32 +0000 Subject: [PATCH 55/57] Prepare 3.12.0 release - Update changelog, readme, supported API versions --- .vscode/launch.json | 1 - ChangeLog.md | 11 +++--- README.md | 33 ++++++++++------- package-lock.json | 36 +++++++++++++------ package.json | 4 +-- src/blob/generated/utils/utils.ts | 2 +- src/blob/utils/constants.ts | 2 +- src/queue/utils/constants.ts | 2 +- .../tableStorageContext.middleware.ts | 8 ++--- src/table/utils/constants.ts | 7 ++-- 10 files changed, 66 insertions(+), 40 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 6f6f7e2b0..95bd0f63c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,7 +15,6 @@ "AZURITE_ACCOUNTS": "" }, "skipFiles": ["node_modules/*/**", "/*/**"], - "outputCapture": "std" }, { diff --git a/ChangeLog.md b/ChangeLog.md index 2ee784da0..3cf0d0c48 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,15 +4,18 @@ ## Upcoming Release +## 2021.4 Version 3.12.0 + Table: +- Preview of Table Service in npm package and docker image. (Visual Studio Code extension doesn't support Table Service in this release) - Allow empty RowKey in an entity. - Fix etag format to be aligned with Azure server. -- Fix delete none exist table error code and error message, to be aligned with Azure server. +- Fix delet none exist table error code and error message, to be aligned with Azure server. - Convert entity properties with type "Edm.DateTime" to UTC time, to be aligned with Azure server. -- Support Batch API -- Allow complex RowKey and PartitionKey in batch API -- Adds support for replaying requests logged in debug logging +- Support Batch API. +- Allow complex RowKey and PartitionKey in batch API. +- Add support for replaying requests logged in debug logging. ## 2021.2 Version 3.11.0 diff --git a/README.md b/README.md index e398947c8..6daf3f78e 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ > Master branch has been updated with latest Azurite V3. > V3 currently only supports Blob and Queue service, please use V2 for Table service for the time being. -| Version | Azure Storage API Version | Service Support | Description | Reference Links | -| ------------------------------------------------------------------ | ------------------------- | --------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 3.11.0 | 2020-06-12 | Blob
Queue | Azurite V3 based on TypeScript & New Architecture | [NPM](https://www.npmjs.com/package/azurite) - [Docker](https://hub.docker.com/_/microsoft-azure-storage-azurite) - [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=Azurite.azurite) | -| [Legacy (v2)](https://github.com/Azure/Azurite/tree/legacy-master) | 2016-05-31 | Blob, Queue and Table | Legacy Azurite V2 | [NPM](https://www.npmjs.com/package/azurite) | +| Version | Azure Storage API Version | Service Support | Description | Reference Links | +| ------------------------------------------------------------------ | ------------------------- | ------------------------------ | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 3.12.0 | 2020-06-12 | Blob, Queue and Table(preview) | Azurite V3 based on TypeScript & New Architecture | [NPM](https://www.npmjs.com/package/azurite) - [Docker](https://hub.docker.com/_/microsoft-azure-storage-azurite) - [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=Azurite.azurite) | +| [Legacy (v2)](https://github.com/Azure/Azurite/tree/legacy-master) | 2016-05-31 | Blob, Queue and Table | Legacy Azurite V2 | [NPM](https://www.npmjs.com/package/azurite) | ## Introduction @@ -37,9 +37,8 @@ Compared to V2, Azurite V3 implements a new architecture leveraging code generat - Preflight Request - Create/List/Delete Queues - Put/Get/Peek/Updata/Deleta/Clear Messages -- Table storage features align with Azure Storage API version 2019-12-12 (Refer to support matrix section below) +- Table storage features align with Azure Storage API version 2020-06-12 (Refer to support matrix section below) - SharedKey/Account SAS/Service SAS - - Get/Set Table Service Properties - Create/List/Delete Tables - Insert/Update/Query/Delete Table Entities - Features **NEW** on V3 @@ -665,6 +664,7 @@ Following files or folders may be created when initializing Azurite in selected - `azurite_db_queue.json` Metadata file used by Azurite queue service. (No when starting Azurite against external database) - `azurite_db_queue_extent.json` Extent metadata file used by Azurite queue service. (No when starting Azurite against external database) - `queuestorage` Persisted bindary data by Azurite queue service. +- `azurite_db_table.json` Metadata file used by Azurite table service. > Note. Delete above files and folders and restart Azurite to clean up Azurite. It will remove all data stored in Azurite!! @@ -791,7 +791,7 @@ All the generated code is kept in `generated` folder, including the generated mi ## Support Matrix -Latest release targets **2020-06-12** API version **blob** service. +Latest release targets **2020-06-12** API version **blob** service. Detailed support matrix: @@ -876,27 +876,34 @@ Detailed support matrix: - SharedKey Lite - Delegation SAS -Latest version supports for **2019-12-12** API version **table** service. +Latest version supports for **2020-06-12** API version **table** service (preview). Detailed support matrix: - Supported Vertical Features + - SharedKeyLite Authentication - SharedKey Authentication - Shared Access Signature Account Level - Shared Access Signature Service Level - Supported REST APIs - List Tables - - Set Service Properties - - Get Service Properties - - Get Stats - Create Table - - Get Table ACL - - Set Table ACL - Delete Table - Update Entity - Query Entities - Merge Entity - Delete Entity - Insert Entity + - Batch +- Following features or REST APIs are NOT supported or limited supported in this release (will support more features per customers feedback in future releases) + - Set Service Properties + - Get Service Properties + - Get Table ACL + - Set Table ACL + - Get Stats + - CORS + - Batch Transaction + - Query with complex conditions + - OAuth ## License diff --git a/package-lock.json b/package-lock.json index 6fb4170a7..cac86b1d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "azurite", - "version": "3.11.0-table-alpha.1", + "version": "3.12.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1096,6 +1096,7 @@ "version": "2.10.3", "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.3.tgz", "integrity": "sha512-IGLs5Xj6kO8Ii90KerQrrwuJKexLgSwYC4oLWmc11mzKe7Jt2E5IVg+ZQ8K53YWZACtVTMBNO3iGuA+4ipjJxQ==", + "dev": true, "requires": { "browserify-mime": "~1.2.9", "extend": "^3.0.2", @@ -1113,12 +1114,14 @@ "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true }, "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -1131,22 +1134,26 @@ "sax": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", - "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=" + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", + "dev": true }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true }, "validator": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz", - "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==" + "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==", + "dev": true }, "xml2js": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", + "dev": true, "requires": { "sax": "0.5.x" } @@ -1154,7 +1161,8 @@ "xmlbuilder": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true } } }, @@ -2209,7 +2217,8 @@ "browserify-mime": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz", - "integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=" + "integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=", + "dev": true }, "buffer-crc32": { "version": "0.2.13", @@ -3647,6 +3656,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, "requires": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -3656,12 +3666,14 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -3671,7 +3683,8 @@ "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==" + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true } } }, @@ -4272,6 +4285,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", + "dev": true, "requires": { "jsonparse": "~1.2.0" } @@ -4312,7 +4326,8 @@ "jsonparse": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz", - "integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=" + "integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=", + "dev": true }, "jsonwebtoken": { "version": "8.5.1", @@ -4726,6 +4741,7 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" diff --git a/package.json b/package.json index 2a9f6cdf4..90a80e0d9 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Azurite", "description": "An open source Azure Storage API compatible server", "icon": "icon.png", - "version": "3.11.0-table-alpha.1", + "version": "3.12.0", "publisher": "Azurite", "categories": [ "Other" @@ -22,7 +22,6 @@ "dependencies": { "@azure/ms-rest-js": "^1.5.0", "args": "^5.0.1", - "azure-storage": "^2.10.3", "etag": "^1.8.1", "express": "^4.16.4", "jsonwebtoken": "^8.5.1", @@ -61,6 +60,7 @@ "@types/validator": "^10.11.3", "@types/vscode": "^1.39.0", "@types/xml2js": "^0.4.3", + "azure-storage": "^2.10.3", "autorest": "^2.0.4413", "axios": "^0.21.1", "cross-env": "^6.0.3", diff --git a/src/blob/generated/utils/utils.ts b/src/blob/generated/utils/utils.ts index 8907780e5..014377abe 100644 --- a/src/blob/generated/utils/utils.ts +++ b/src/blob/generated/utils/utils.ts @@ -3,7 +3,7 @@ import URITemplate from "uri-templates"; export function isURITemplateMatch(url: string, template: string): boolean { const uriTemplate = URITemplate(template); // TODO: Fixing $ parsing issue such as $logs container cannot work in strict mode issue - const result = (uriTemplate.fromUri as any)(url, { strict: false }); + const result = (uriTemplate.fromUri as any)(url, { strict: true }); if (result === undefined) { return false; } diff --git a/src/blob/utils/constants.ts b/src/blob/utils/constants.ts index d80a8a7a6..74d50402b 100644 --- a/src/blob/utils/constants.ts +++ b/src/blob/utils/constants.ts @@ -1,7 +1,7 @@ import { StoreDestinationArray } from "../../common/persistence/IExtentStore"; import * as Models from "../generated/artifacts/models"; -export const VERSION = "3.11.0"; +export const VERSION = "3.12.0"; export const BLOB_API_VERSION = "2020-06-12"; export const DEFAULT_BLOB_SERVER_HOST_NAME = "127.0.0.1"; // Change to 0.0.0.0 when needs external access export const DEFAULT_LIST_BLOBS_MAX_RESULTS = 5000; diff --git a/src/queue/utils/constants.ts b/src/queue/utils/constants.ts index de0376775..910cee1cc 100644 --- a/src/queue/utils/constants.ts +++ b/src/queue/utils/constants.ts @@ -1,6 +1,6 @@ import { StoreDestinationArray } from "../../common/persistence/IExtentStore"; -export const VERSION = "3.11.0"; +export const VERSION = "3.12.0"; export const QUEUE_API_VERSION = "2020-06-12"; export const DEFAULT_QUEUE_SERVER_HOST_NAME = "127.0.0.1"; // Change to 0.0.0.0 when needs external access export const DEFAULT_QUEUE_LISTENING_PORT = 10001; diff --git a/src/table/middleware/tableStorageContext.middleware.ts b/src/table/middleware/tableStorageContext.middleware.ts index 321367224..6dedbf5e6 100644 --- a/src/table/middleware/tableStorageContext.middleware.ts +++ b/src/table/middleware/tableStorageContext.middleware.ts @@ -7,7 +7,8 @@ import TableStorageContext from "../context/TableStorageContext"; import { DEFAULT_TABLE_CONTEXT_PATH, HeaderConstants, - ValidAPIVersions + ValidAPIVersions, + VERSION } from "../utils/constants"; import { checkApiVersion } from "../utils/utils"; @@ -34,10 +35,7 @@ export function tableStorageContextMiddleware( skipApiVersionCheck?: boolean ): void { // Set server header in every Azurite response - res.setHeader( - HeaderConstants.SERVER, - `Azurite-Table/${HeaderConstants.VERSION}` - ); + res.setHeader(HeaderConstants.SERVER, `Azurite-Table/${VERSION}`); const requestID = uuid(); diff --git a/src/table/utils/constants.ts b/src/table/utils/constants.ts index 8f6846e22..34cdfc566 100644 --- a/src/table/utils/constants.ts +++ b/src/table/utils/constants.ts @@ -13,11 +13,11 @@ export enum TABLE_STATUSCODE { } export const DEFAULT_TABLE_CONTEXT_PATH = "azurite_table_context"; -export const TABLE_API_VERSION = "2019-12-12"; +export const TABLE_API_VERSION = "2020-06-12"; +export const VERSION = "3.12.0"; export const HeaderConstants = { SERVER: "Server", - VERSION: "3.9.0-table-alpha.1", APPLICATION_JSON: "application/json", AUTHORIZATION: "authorization", CONTENT_MD5: "content-md5", @@ -43,6 +43,9 @@ export const RETURN_CONTENT = "return-content"; export const QUERY_RESULT_MAX_NUM = 1000; export const ValidAPIVersions = [ + "2020-06-12", + "2020-04-08", + "2020-02-10", "2019-12-12", "2019-10-10", "2019-07-07", From 0ce0316826a318471c0bd00c45fc89980f29c15f Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Fri, 30 Apr 2021 04:04:14 +0000 Subject: [PATCH 56/57] Update table into CI --- azure-pipelines.yml | 3 +++ package.json | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7671de4c1..5e665d45f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -353,6 +353,7 @@ jobs: azurite -v azurite-blob -v azurite-queue -v + azurite-table -v workingDirectory: "./" displayName: "Validate npm global installation from GitHub code base" @@ -401,6 +402,7 @@ jobs: azurite -v azurite-blob -v azurite-queue -v + azurite-table -v workingDirectory: "./" displayName: "Validate npm global installation from GitHub code base" @@ -449,6 +451,7 @@ jobs: azurite -v azurite-blob -v azurite-queue -v + azurite-table -v workingDirectory: "./" displayName: "Validate npm global installation from GitHub code base" diff --git a/package.json b/package.json index 90a80e0d9..1fa2f80fd 100644 --- a/package.json +++ b/package.json @@ -236,8 +236,8 @@ "test:table": "npm run lint && cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 mocha --compilers ts-node/register --no-timeouts --recursive tests/table/*.test.ts tests/table/apis/*.test.ts tests/table/apis/**/*.test.ts", "clean": "rimraf dist typings *.log coverage __testspersistence__ temp __testsstorage__ .nyc_output debug.log *.vsix *.tgz", "clean:deep": "npm run clean && rimraf debug.log __*", - "validate:npmpack:win": "npm install && npm run build && npm pack && cross-var npm install -g azurite-$npm_package_version.tgz && azurite -v && azurite-blob -v && azurite-queue -v", - "validate:npmpack:linux_mac": "npm install && npm run build && npm pack && cross-var sudo npm install -g azurite-$npm_package_version.tgz && azurite -v && azurite-blob -v && azurite-queue -v", + "validate:npmpack:win": "npm install && npm run build && npm pack && cross-var npm install -g azurite-$npm_package_version.tgz && azurite -v && azurite-blob -v && azurite-queue -v && azurite-table -v", + "validate:npmpack:linux_mac": "npm install && npm run build && npm pack && cross-var sudo npm install -g azurite-$npm_package_version.tgz && azurite -v && azurite-blob -v && azurite-queue -v && azurite-table -v", "db:migrate:blob:metadata": "sequelize db:migrate --config migrations/blob/metadata/config/config.json --migrations-path migrations/blob/metadata/migrations", "db:create:blob:metadata": "sequelize db:create --config migrations/blob/metadata/config/config.json --migrations-path migrations/blob/metadata/migrations" }, From 2296008415ffa3d6e74a37061ed6451541361dc3 Mon Sep 17 00:00:00 2001 From: xiaonlimsft Date: Fri, 30 Apr 2021 14:18:45 +0800 Subject: [PATCH 57/57] 3.12.0 table (#769) * Skip files for vspackage * Update Notice.txt --- .vscodeignore | 5 +- NOTICE.txt | 21568 +++++++++--------------------------------------- 2 files changed, 4077 insertions(+), 17496 deletions(-) diff --git a/.vscodeignore b/.vscodeignore index a9387e324..70ed976ae 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -26,4 +26,7 @@ __blobstorage__ __queueTestsPersistence__ __* *.env -temp \ No newline at end of file +temp +.github +.prettierrc.json +README.mcr.md \ No newline at end of file diff --git a/NOTICE.txt b/NOTICE.txt index 75ebcf632..5e00132ee 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -15,11 +15,22 @@ USA Notwithstanding any other terms, you may reverse engineer this software to the extent required to debug changes to any libraries licensed under the GNU Lesser General Public License. +--------------------------------------------------------- -------------------------------------------------------------------- +json-schema 0.2.3 - AFL-2.1 OR BSD-3-Clause +https://github.com/kriszyp/json-schema#readme + +Copyright (c) 2007 Kris Zyp SitePen (www.sitepen.com) + +AFL-2.1 OR BSD-3-Clause + +--------------------------------------------------------- + +--------------------------------------------------------- adal-node 0.1.28 - Apache-2.0 https://github.com/AzureAD/azure-activedirectory-library-for-nodejs#readme + Copyright (c) Microsoft Open Technologies, Inc.  Apache License @@ -225,12 +236,13 @@ Copyright (c) Microsoft Open Technologies, Inc. limitations under the License. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- aws-sign2 0.7.0 - Apache-2.0 https://github.com/mikeal/aws-sign#readme + Copyright 2010 LearnBoost Apache License @@ -289,13 +301,14 @@ If the Work includes a "NOTICE" text file as part of its distribution, then any END OF TERMS AND CONDITIONS -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- caseless 0.12.0 - Apache-2.0 https://github.com/mikeal/caseless#readme + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -325,12 +338,13 @@ If the Work includes a "NOTICE" text file as part of its distribution, then any 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- denque 1.4.1 - Apache-2.0 https://github.com/invertase/denque#readme + Copyright (c) 2018 Mike Diarmid Copyright (c) 2018 Mike Diarmid (Salakar) @@ -348,37 +362,13 @@ See the License for the specific language governing permissions and limitations under the License. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -didyoumean 1.2.1 - Apache-2.0 -https://github.com/dcporter/didyoumean.js -copyright (c) 2013 Dave Porter. -copyright (c) 2013-2014 Dave Porter. - -## License - -didYouMean.js copyright (c) 2013 Dave Porter. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License -[here](http://www.apache.org/licenses/LICENSE-2.0). - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - - -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- ecdsa-sig-formatter 1.0.11 - Apache-2.0 https://github.com/Brightspace/node-ecdsa-sig-formatter#readme + Copyright 2015 D2L Corporation Apache License @@ -584,13 +574,14 @@ Apache License limitations under the License. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- forever-agent 0.6.1 - Apache-2.0 https://github.com/mikeal/forever-agent + Apache License Version 2.0, January 2004 @@ -647,13 +638,14 @@ If the Work includes a "NOTICE" text file as part of its distribution, then any END OF TERMS AND CONDITIONS -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -jsbi 3.1.1 - Apache-2.0 +jsbi 3.1.4 - Apache-2.0 https://github.com/GoogleChromeLabs/jsbi#readme + Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ @@ -832,14 +824,15 @@ https://github.com/GoogleChromeLabs/jsbi#readme END OF TERMS AND CONDITIONS -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- long 4.0.0 - Apache-2.0 https://github.com/dcodeIO/long.js#readme + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1043,13 +1036,14 @@ https://github.com/dcodeIO/long.js#readme limitations under the License. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- oauth-sign 0.9.0 - Apache-2.0 https://github.com/mikeal/oauth-sign#readme + Apache License Version 2.0, January 2004 @@ -1106,12 +1100,13 @@ If the Work includes a "NOTICE" text file as part of its distribution, then any END OF TERMS AND CONDITIONS -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -request 2.88.0 - Apache-2.0 +request 2.88.2 - Apache-2.0 https://github.com/request/request#readme + Copyright 2010-2012 Mikeal Rogers Apache License @@ -1170,1049 +1165,13 @@ If the Work includes a "NOTICE" text file as part of its distribution, then any END OF TERMS AND CONDITIONS -------------------------------------------------------------------- - -------------------------------------------------------------------- - -rxjs 6.5.3 - Apache-2.0 -https://github.com/ReactiveX/RxJS -Copyright Google Inc. -Copyright (c) Microsoft Corporation. -Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -spdx-correct 3.1.0 - Apache-2.0 -https://github.com/jslicense/spdx-correct.js#readme - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- tslib 1.10.0 - Apache-2.0 http://typescriptlang.org/ + Copyright (c) Microsoft Corporation. Apache License @@ -2272,231 +1231,14 @@ If the Work includes a "NOTICE" text file as part of its distribution, then any END OF TERMS AND CONDITIONS -------------------------------------------------------------------- - -------------------------------------------------------------------- +--------------------------------------------------------- -tslint 5.20.0 - Apache-2.0 -https://palantir.github.io/tslint -Copyright 2018 -Copyright 2013 Palantir Technologies, Inc. -Copyright 2014 Palantir Technologies, Inc. -Copyright 2015 Palantir Technologies, Inc. -Copyright 2016 Palantir Technologies, Inc. -Copyright 2017 Palantir Technologies, Inc. -Copyright 2018 Palantir Technologies, Inc. -Copyright 2019 Palantir Technologies, Inc. - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- +--------------------------------------------------------- tunnel-agent 0.6.0 - Apache-2.0 https://github.com/mikeal/tunnel-agent#readme + Apache License Version 2.0, January 2004 @@ -2553,13222 +1295,1135 @@ If the Work includes a "NOTICE" text file as part of its distribution, then any END OF TERMS AND CONDITIONS -------------------------------------------------------------------- - -------------------------------------------------------------------- +--------------------------------------------------------- -typescript 3.6.3 - Apache-2.0 -https://www.typescriptlang.org/ -(c) by W3C -Copyright Grant. I -Copyright (c) 2018 WHATWG -Copyright (c) Microsoft Corporation. -Copyright (c) 1991-2017 Unicode, Inc. -Copyright (c) 2018 The Khronos Group Inc. -Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS +--------------------------------------------------------- -Apache License +esprima 4.0.1 - BSD-2-Clause +http://esprima.org/ -Version 2.0, January 2004 +Copyright JS Foundation and other contributors, https://js.foundation -http://www.apache.org/licenses/ +Copyright JS Foundation and other contributors, https://js.foundation/ -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: -1. Definitions. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. -"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. -"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. +--------------------------------------------------------- -"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. +--------------------------------------------------------- -"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. +uri-js 4.4.0 - BSD-2-Clause +https://github.com/garycourt/uri-js -"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. +(c) 2011 Gary Court. +Copyright 2011 Gary Court. -"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). +Copyright 2011 Gary Court. All rights reserved. -"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. +THIS SOFTWARE IS PROVIDED BY GARY COURT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. +The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Gary Court. -4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: -You must give any other recipients of the Work or Derivative Works a copy of this License; and +--------------------------------------------------------- -You must cause any modified files to carry prominent notices stating that You changed the files; and +--------------------------------------------------------- -You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +@js-joda/core 3.1.0 - BSD-3-Clause +https://js-joda.github.io/js-joda -If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. +copyright (c) 2016, Philipp Thurwachter, Pattrick Huper +Copyright (c) 2016, Philipp Thurwachter & Pattrick Huper +copyright (c) 2016, Philipp Thurwachter & Pattrick Huper +copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos +copyright (c) 2015-present, Philipp Thurwachter, Pattrick Huper & js-joda contributors -5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. +BSD License -6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. +For js-joda software -7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -validate-npm-package-license 3.0.4 - Apache-2.0 -https://github.com/kemitchell/validate-npm-package-license.js#readme - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cls-bluebird 2.1.0 - BSD-2-Clause -https://github.com/TimBeyer/cls-bluebird#readme - -Copyright (c) . All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -css-select 1.2.0 - BSD-2-Clause -https://github.com/fb55/css-select#readme -Copyright (c) Felix Bohm - -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -css-what 2.1.3 - BSD-2-Clause -https://github.com/fb55/css-what#readme -Copyright (c) Felix Bohm - -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -domelementtype 1.3.1 - BSD-2-Clause -https://github.com/fb55/domelementtype#readme -Copyright (c) Felix Bohm - -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -domhandler 2.4.2 - BSD-2-Clause -https://github.com/fb55/DomHandler#readme -Copyright (c) Felix Bohm - -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -domutils 1.5.1 - BSD-2-Clause -https://github.com/FB55/domutils -Copyright (c) Felix Bohm - -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -entities 1.1.2 - BSD-2-Clause -https://github.com/fb55/entities#readme -Copyright (c) Felix Bohm -(c) // http://mathiasbynens.be/notes/javascript-encoding - -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -esprima 4.0.1 - BSD-2-Clause -http://esprima.org -Copyright JS Foundation and other contributors, https://js.foundation - -Copyright JS Foundation and other contributors, https://js.foundation/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -esutils 2.0.3 - BSD-2-Clause -https://github.com/estools/esutils -Copyright (c) 2014 Ivan Nikulin -Copyright (c) 2013 Yusuke Suzuki -Copyright (c) 2013-2014 Yusuke Suzuki -Copyright (c) 2013 Yusuke Suzuki (http://github.com/Constellation) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -normalize-package-data 2.5.0 - BSD-2-Clause -https://github.com/npm/normalize-package-data#readme -Copyright (c) Meryn Stol -Copyright (c) 2013 Meryn Stol - -This package contains code originally written by Isaac Z. Schlueter. -Used with permission. - -Copyright (c) Meryn Stol ("Author") -All rights reserved. - -The BSD License - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -nth-check 1.0.2 - BSD-2-Clause -https://github.com/fb55/nth-check -Copyright (c) Felix Bohm - -Copyright (c) Felix Böhm -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -regjsparser 0.1.5 - BSD-2-Clause -https://github.com/jviereck/regjsparser - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -shimmer 1.2.1 - BSD-2-Clause -https://github.com/othiym23/shimmer#readme -Copyright (c) 2013-2019, Forrest L Norvell - -BSD 2-Clause License - -Copyright (c) 2013-2019, Forrest L Norvell -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -staged-git-files 1.1.2 - BSD-2-Clause -https://github.com/mcwhittemore/staged-git-files#readme -Copied (c) Deleted - -Copyright (c) . All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -stringify-object 3.3.0 - BSD-2-Clause -https://github.com/yeoman/stringify-object#readme -(c) Yeoman team -Copyright (c) 2015, Yeoman team - -Copyright (c) 2015, Yeoman team -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -uri-js 4.2.2 - BSD-2-Clause -https://github.com/garycourt/uri-js -(c) 2011 Gary Court. -Copyright 2011 Gary Court. -Copyright (c) 2008 Ariel Flesler -Copyright (c) 2009 John Resig, Jorn Zaefferer - -Copyright (c) . All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -bcrypt-pbkdf 1.0.2 - BSD-3-Clause -https://github.com/joyent/node-bcrypt-pbkdf#readme -Copyright 2016, Joyent Inc -Copyright (c) 2013 Ted Unangst -Copyright 1997 Niels Provos - -The Blowfish portions are under the following license: - -Blowfish block cipher for OpenBSD -Copyright 1997 Niels Provos -All rights reserved. - -Implementation advice by David Mazieres . - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -The bcrypt_pbkdf portions are under the following license: - -Copyright (c) 2013 Ted Unangst - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - - -Performance improvements (Javascript-specific): - -Copyright 2016, Joyent Inc -Author: Alex Wilson - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -buffer-equal-constant-time 1.0.1 - BSD-3-Clause -(c) 2013 GoInstant Inc., a salesforce.com company -Copyright (c) 2013, GoInstant Inc., a salesforce.com company - -Copyright (c) 2013, GoInstant Inc., a salesforce.com company -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -* Neither the name of salesforce.com, nor GoInstant, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -diff 3.5.0 - BSD-3-Clause -https://github.com/kpdecker/jsdiff#readme -Copyright (c) 2009-2015, Kevin Decker - -Software License Agreement (BSD License) - -Copyright (c) 2009-2015, Kevin Decker - -All rights reserved. - -Redistribution and use of this software in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Kevin Decker nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -diff 4.0.1 - BSD-3-Clause -https://github.com/kpdecker/jsdiff#readme -Copyright (c) 2009-2015, Kevin Decker - -Software License Agreement (BSD License) - -Copyright (c) 2009-2015, Kevin Decker - -All rights reserved. - -Redistribution and use of this software in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Kevin Decker nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -qs 6.5.2 - BSD-3-Clause -https://github.com/ljharb/qs -Copyright (c) 2014 Nathan LaFreniere and other contributors. - -Copyright (c) 2014 Nathan LaFreniere and other contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of any contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * * * - -The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -qs 6.7.0 - BSD-3-Clause -https://github.com/ljharb/qs -Copyright (c) 2014 Nathan LaFreniere and other contributors. - -Copyright (c) 2014 Nathan LaFreniere and other contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of any contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - * * * - -The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -source-map 0.5.7 - BSD-3-Clause -https://github.com/mozilla/source-map -Copyright 2011 The Closure Compiler -Copyright 2011 Mozilla Foundation and contributors -Copyright 2014 Mozilla Foundation and contributors -Copyright 2009-2011 Mozilla Foundation and contributors -Copyright (c) 2009-2011, Mozilla Foundation and contributors - - -Copyright (c) 2009-2011, Mozilla Foundation and contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the names of the Mozilla Foundation nor the names of project - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -source-map 0.6.1 - BSD-3-Clause -https://github.com/mozilla/source-map -Copyright 2011 The Closure Compiler -Copyright 2011 Mozilla Foundation and contributors -Copyright 2014 Mozilla Foundation and contributors -Copyright 2009-2011 Mozilla Foundation and contributors -Copyright (c) 2009-2011, Mozilla Foundation and contributors - - -Copyright (c) 2009-2011, Mozilla Foundation and contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the names of the Mozilla Foundation nor the names of project - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -sprintf-js 1.0.3 - BSD-3-Clause -https://github.com/alexei/sprintf.js#readme -Copyright (c) 2007-2014, Alexandru Marasteanu - -Copyright (c) 2007-2014, Alexandru Marasteanu -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -* Neither the name of this software nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -sprintf-js 1.1.2 - BSD-3-Clause -https://github.com/alexei/sprintf.js#readme -Copyright (c) 2007-present, Alexandru Marasteanu - -Copyright (c) 2007-present, Alexandru Mărășteanu -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -* Neither the name of this software nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -synchronous-promise 2.0.10 - BSD-3-Clause -https://github.com/fluffynuts/synchronous-promise#readme -Copyright (c) 2016, Davyd McColl - -Copyright (c) 2016, Davyd McColl -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of synchronous-promise nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -tough-cookie 2.4.3 - BSD-3-Clause -https://github.com/salesforce/tough-cookie -Copyright (c) 2015, Salesforce.com, Inc. -Copyright (c) 2018, Salesforce.com, Inc. - -Copyright (c) 2015, Salesforce.com, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -tough-cookie 3.0.1 - BSD-3-Clause -https://github.com/salesforce/tough-cookie -Copyright (c) 2015, Salesforce.com, Inc. -Copyright (c) 2018, Salesforce.com, Inc. - -Copyright (c) 2015, Salesforce.com, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -tough-cookie 2.5.0 - BSD-3-Clause -https://github.com/salesforce/tough-cookie -Copyright (c) 2015, Salesforce.com, Inc. -Copyright (c) 2018, Salesforce.com, Inc. - -Copyright (c) 2015, Salesforce.com, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -spdx-exceptions 2.2.0 - CC-BY-3.0 -https://github.com/kemitchell/spdx-exceptions.json#readme -Copyright (c) 2010-2015 Linux Foundation and its Contributors. - -Creative Commons Attribution 3.0 Unported CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. - -License - -THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. - -BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. - - 1. Definitions - - a. "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. - - b. "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License. - - c. "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. - - d. "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. - - e. "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. - - f. "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. - - g. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. - - h. "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. - - i. "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. - - 2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. - - 3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: - - a. to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; - - b. to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; - - c. to Distribute and Publicly Perform the Work including as incorporated in Collections; and, - - d. to Distribute and Publicly Perform Adaptations. - - e. For the avoidance of doubt: - - i. Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; - - ii. Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and, - - iii. Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License. - - The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved. - - 4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: - - a. You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(b), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(b), as requested. - - b. If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv), consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4 (b) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. - - c. Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. - - 5. Representations, Warranties and Disclaimer - - UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. - - 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - - 7. Termination - - a. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. - - b. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. - - 8. Miscellaneous - - a. Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. - - b. Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. - - c. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. - - d. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. - - e. This License may not be modified without the mutual written agreement of the Licensor and You. - - f. The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. - -Creative Commons Notice - -Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor. - -Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, Creative Commons does not authorize the use by either party of the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. For the avoidance of doubt, this trademark restriction does not form part of this License. - -Creative Commons may be contacted at http://creativecommons.org/. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -spdx-license-ids 3.0.5 - CC0-1.0 -https://github.com/shinnn/spdx-license-ids#readme - -Creative Commons Legal Code - -CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. - -Statement of Purpose - -The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). - -Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. - -For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. - - 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: - - i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; - - ii. moral rights retained by the original author(s) and/or performer(s); - - iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; - - iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; - - v. rights protecting the extraction, dissemination, use and reuse of data in a Work; - - vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and - - vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. - - 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. - - 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. - - 4. Limitations and Disclaimers. - - a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. - - b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. - - c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. - - d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -boolbase 1.0.0 - ISC -https://github.com/fb55/boolbase - -ISC License - -Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") - -Copyright (c) 1995-2003 by Internet Software Consortium - -Permission to use, copy, modify, and /or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -browser-stdout 1.3.1 - ISC -https://github.com/kumavis/browser-stdout#readme -Copyright 2018 - -Copyright 2018 kumavis - -Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fs.realpath 1.0.0 - ISC -https://github.com/isaacs/fs.realpath#readme -Copyright (c) Isaac Z. Schlueter and Contributors -Copyright Joyent, Inc. and other Node contributors. - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ----- - -This library bundles a version of the `fs.realpath` and `fs.realpathSync` -methods from Node.js v0.10 under the terms of the Node.js MIT license. - -Node's license follows, also included at the header of `old.js` which contains -the licensed code: - - Copyright Joyent, Inc. and other Node contributors. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -get-own-enumerable-property-symbols 3.0.0 - ISC -https://github.com/mightyiam/get-own-enumerable-property-symbols#readme - -ISC License - -Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") - -Copyright (c) 1995-2003 by Internet Software Consortium - -Permission to use, copy, modify, and /or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -glob 7.1.4 - ISC -https://github.com/isaacs/node-glob#readme - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -## Glob Logo - -Glob's logo created by Tanya Brassie , licensed -under a Creative Commons Attribution-ShareAlike 4.0 International License -https://creativecommons.org/licenses/by-sa/4.0/ - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -glob 7.1.2 - ISC -https://github.com/isaacs/node-glob#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -har-schema 2.0.0 - ISC -https://github.com/ahmadnassri/har-schema -Copyright (c) 2015, Ahmad Nassri -copyright ahmadnassri.com (https://www.ahmadnassri.com/) - -Copyright (c) 2015, Ahmad Nassri - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -hosted-git-info 2.8.4 - ISC -https://github.com/npm/hosted-git-info -Copyright (c) 2015, Rebecca Turner - -Copyright (c) 2015, Rebecca Turner - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -inflight 1.0.6 - ISC -https://github.com/isaacs/inflight -Copyright (c) Isaac Z. Schlueter - -The ISC License - -Copyright (c) Isaac Z. Schlueter - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -inherits 2.0.3 - ISC -https://github.com/isaacs/inherits#readme -Copyright (c) Isaac Z. Schlueter - -The ISC License - -Copyright (c) Isaac Z. Schlueter - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -isexe 2.0.0 - ISC -https://github.com/isaacs/isexe#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -json-stringify-safe 5.0.1 - ISC -https://github.com/isaacs/json-stringify-safe -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -lru-cache 4.1.5 - ISC -https://github.com/isaacs/node-lru-cache#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -lru-cache 5.1.1 - ISC -https://github.com/isaacs/node-lru-cache#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -make-error 1.3.5 - ISC -https://github.com/JsCommunity/make-error -Copyright 2014 Julien Fontanet -(c) Julien Fontanet (http://julien.isonoe.net) - -Copyright 2014 Julien Fontanet - -Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -minimatch 3.0.4 - ISC -https://github.com/isaacs/minimatch#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -mute-stream 0.0.8 - ISC -https://github.com/isaacs/mute-stream#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -once 1.4.0 - ISC -https://github.com/isaacs/once#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -osenv 0.1.5 - ISC -https://github.com/npm/osenv#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -pseudomap 1.0.2 - ISC -https://github.com/isaacs/pseudomap#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -read 1.0.7 - ISC -https://github.com/isaacs/read#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -rimraf 2.7.1 - ISC -https://github.com/isaacs/rimraf#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -sax 1.2.4 - ISC -https://github.com/isaacs/sax-js#readme -Copyright (c) Isaac Z. Schlueter and Contributors -Copyright Mathias Bynens - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -==== - -`String.fromCodePoint` by Mathias Bynens used according to terms of MIT -License, as follows: - - Copyright Mathias Bynens - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -semver 6.3.0 - ISC -https://github.com/npm/node-semver#readme -Copyright Isaac Z. -Copyright Isaac Z. Schlueter -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -setprototypeof 1.1.1 - ISC -https://github.com/wesleytodd/setprototypeof -Copyright (c) 2015, Wes Todd - -Copyright (c) 2015, Wes Todd - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -signal-exit 3.0.2 - ISC -https://github.com/tapjs/signal-exit -Copyright (c) 2015 - -The ISC License - -Copyright (c) 2015, Contributors - -Permission to use, copy, modify, and/or distribute this software -for any purpose with or without fee is hereby granted, provided -that the above copyright notice and this permission notice -appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE -LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -which 1.3.1 - ISC -https://github.com/isaacs/node-which#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -which 2.0.1 - ISC -https://github.com/isaacs/node-which#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -wrappy 1.0.2 - ISC -https://github.com/npm/wrappy -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -yallist 2.1.2 - ISC -https://github.com/isaacs/yallist#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -yallist 3.1.1 - ISC -https://github.com/isaacs/yallist#readme -Copyright (c) Isaac Z. Schlueter and Contributors - -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@azure/ms-rest-azure-env 1.1.2 - MIT -https://github.com/Azure/ms-rest-azure-env -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@azure/ms-rest-js 1.8.13 - MIT -https://github.com/Azure/ms-rest-js -Copyright (c) Microsoft Corporation. -Copyright (c) 2010-2016 Robert Kieffer and other contributors - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@azure/ms-rest-js 2.0.4 - MIT -https://github.com/Azure/ms-rest-js -copyright 2015 Toru Nagashima. -Copyright (c) Microsoft Corporation. -Copyright (c) 2010-2016 Robert Kieffer and other contributors - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@azure/ms-rest-nodeauth 2.0.2 - MIT -https://github.com/Azure/ms-rest-nodeauth -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@azure/storage-blob 10.5.0 - MIT -https://github.com/Azure/azure-sdk-for-js#readme -Copyright (c) Microsoft Corporation. -Copyright (c) Microsoft and contributors. -Copyright Joyent, Inc. and other Node contributors. -Copyright (c) 2010-2016 Robert Kieffer and other contributors - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@azure/storage-queue 10.3.0 - MIT -https://github.com/Azure/azure-sdk-for-js#readme -Copyright (c) Microsoft Corporation. -Copyright (c) Microsoft and contributors. -Copyright (c) 2010-2016 Robert Kieffer and other contributors - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@babel/code-frame 7.5.5 - MIT -https://babeljs.io/ -Copyright (c) 2014-present Sebastian McKenzie and other contributors - -MIT License - -Copyright (c) 2014-present Sebastian McKenzie and other contributors - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@babel/highlight 7.5.0 - MIT -https://babeljs.io/ -Copyright (c) 2014-present Sebastian McKenzie and other contributors - -MIT License - -Copyright (c) 2014-present Sebastian McKenzie and other contributors - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@babel/runtime 7.6.0 - MIT -Copyright (c) 2014-present Sebastian McKenzie and other contributors - -MIT License - -Copyright (c) 2014-present Sebastian McKenzie and other contributors - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@samverschueren/stream-to-observable 0.3.0 - MIT -https://github.com/SamVerschueren/stream-to-observable#readme -Copyright (c) James Talmage - -The MIT License (MIT) - -Copyright (c) James Talmage (github.com/jamestalmage), Sam Verschueren (github.com/SamVerschueren) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/args 3.0.0 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/async 3.0.1 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/bluebird 3.5.27 - MIT -Copyright (c) 2016 -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/body-parser 1.17.1 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/connect 3.4.32 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/etag 1.8.0 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/events 3.0.0 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/express 4.17.1 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/express-serve-static-core 4.16.9 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/glob 7.1.1 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/jsonwebtoken 8.3.9 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/lokijs 1.5.2 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/mime 2.0.1 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/minimatch 3.0.3 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/mocha 5.2.7 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/morgan 1.7.37 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/multistream 2.1.1 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/node 12.7.5 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/node 8.10.59 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/node 12.12.22 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/node 13.1.0 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/node-fetch 2.5.0 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/range-parser 1.2.3 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/readable-stream 2.3.5 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/rimraf 2.0.2 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/serve-static 1.13.3 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/tunnel 0.0.1 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/tunnel 0.0.0 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/uri-templates 0.1.30 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/uuid 3.4.5 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/validator 10.11.3 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/vscode 1.39.0 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -@types/xml2js 0.4.5 - MIT -Copyright (c) Microsoft Corporation. - - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -abort-controller 3.0.0 - MIT -https://github.com/mysticatea/abort-controller#readme -copyright 2015 Toru Nagashima. -Copyright (c) 2017 Toru Nagashima - -MIT License - -Copyright (c) 2017 Toru Nagashima - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -accepts 1.3.7 - MIT -https://github.com/jshttp/accepts#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015 Douglas Christopher Wilson -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ajv 6.10.2 - MIT -https://github.com/epoberezkin/ajv -(c) 2011 Gary Court. -Copyright 2011 Gary Court. -Copyright (c) 2015-2017 Evgeny Poberezkin - -The MIT License (MIT) - -Copyright (c) 2015-2017 Evgeny Poberezkin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ansi-escapes 3.2.0 - MIT -https://github.com/sindresorhus/ansi-escapes#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ansi-regex 3.0.0 - MIT -https://github.com/chalk/ansi-regex#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ansi-regex 2.1.1 - MIT -https://github.com/chalk/ansi-regex#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ansi-styles 2.2.1 - MIT -https://github.com/chalk/ansi-styles#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ansi-styles 3.2.1 - MIT -https://github.com/chalk/ansi-styles#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ansicolors 0.3.2 - MIT -Copyright 2013 Thorsten Lorenz. - -Copyright 2013 Thorsten Lorenz. -All rights reserved. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -any-observable 0.3.0 - MIT -https://github.com/sindresorhus/any-observable#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -any-promise 1.3.0 - MIT -http://github.com/kevinbeaty/any-promise -Copyright (c) 2014-2016 Kevin Beaty - -Copyright (C) 2014-2016 Kevin Beaty - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -argparse 1.0.10 - MIT -https://github.com/nodeca/argparse#readme -Copyright (c) 2012 by Vitaly Puzrin -Copyright (c) 2012 Vitaly Puzrin (https://github.com/puzrin). - -(The MIT License) - -Copyright (C) 2012 by Vitaly Puzrin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -args 5.0.1 - MIT -https://github.com/leo/args#readme -Copyright (c) 2016 Leonard Lamprecht - -The MIT License (MIT) - -Copyright (c) 2016 Leonard Lamprecht - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -arr-diff 4.0.0 - MIT -https://github.com/jonschlinkert/arr-diff -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -arr-flatten 1.1.0 - MIT -https://github.com/jonschlinkert/arr-flatten -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -arr-union 3.1.0 - MIT -https://github.com/jonschlinkert/arr-union -Copyright (c) 2014-2016, Jon Schlinkert. -Copyright (c) 2016 Jon Schlinkert (https://github.com/jonschlinkert) - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -array-flatten 1.1.1 - MIT -https://github.com/blakeembrey/array-flatten -Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) - -The MIT License (MIT) - -Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -array-union 1.0.2 - MIT -https://github.com/sindresorhus/array-union#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -array-uniq 1.0.3 - MIT -https://github.com/sindresorhus/array-uniq#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -array-unique 0.3.2 - MIT -https://github.com/jonschlinkert/array-unique -Copyright (c) 2014-2016, Jon Schlinkert -Copyright (c) 2014-2015, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -arrify 1.0.1 - MIT -https://github.com/sindresorhus/arrify#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -asn1 0.2.4 - MIT -https://github.com/joyent/node-asn1#readme -Copyright (c) 2011 Mark Cavage -Copyright 2011 Mark Cavage - -Copyright (c) 2011 Mark Cavage, All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -assert-plus 1.0.0 - MIT -https://github.com/mcavage/node-assert-plus#readme -Copyright 2015 Joyent, Inc. -Copyright (c) 2012 Mark Cavage -Copyright (c) 2012, Mark Cavage. - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -assign-symbols 1.0.0 - MIT -https://github.com/jonschlinkert/assign-symbols -Copyright (c) 2015 Jon Schlinkert -Copyright (c) 2015, Jon Schlinkert. - -The MIT License (MIT) - -Copyright (c) 2015, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -async 2.6.3 - MIT -https://caolan.github.io/async/ -Copyright (c) 2010-2018 Caolan McMahon - -Copyright (c) 2010-2018 Caolan McMahon - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -asynckit 0.4.0 - MIT -https://github.com/alexindigo/asynckit#readme -Copyright (c) 2016 Alex Indigo - -The MIT License (MIT) - -Copyright (c) 2016 Alex Indigo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -autorest 2.0.4283 - MIT -https://github.com/Azure/autorest/blob/master/README.md -(c) 2018 Microsoft Corporation. -Copyright (c) Microsoft Corporation. - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -aws4 1.9.0 - MIT -https://github.com/mhart/aws4#readme -Copyright 2013 Michael Hart (michael.hart.au@gmail.com) - -Copyright 2013 Michael Hart (michael.hart.au@gmail.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -axios 0.19.0 - MIT -https://github.com/axios/axios -(c) 2019 by Matt Zabriskie -Copyright (c) 2014-present Matt Zabriskie - -Copyright (c) 2014-present Matt Zabriskie - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -azure-devops-node-api 7.2.0 - MIT -https://github.com/Microsoft/azure-devops-node-api#readme -Copyright (c) Microsoft. -Copyright (c) 2014 Tyler Kellen -Copyright (c) 2015 Tyler Kellen -Copyright (c) Isaac Z. Schlueter -Copyright (c) 2012 Koichi Kobayashi -Copyright (c) Microsoft Corporation. -Copyright (c) Isaac Z. Schlueter and Contributors -Copyright Joyent, Inc. and other Node contributors. -Copyright (c) 2012, Artur Adib -Copyright (c) 2013 Julian Gruber -Copyright (c) Sindre Sorhus (sindresorhus.com) -Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - -Visual Studio Team Services Client for Node.js - -Copyright (c) Microsoft Corporation - -All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-code-frame 6.26.0 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-core 6.26.3 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-generator 6.26.1 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-bindify-decorators 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-builder-binary-assignment-operator-visitor 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-call-delegate 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-define-map 6.26.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-explode-assignable-expression 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-explode-class 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-function-name 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-get-function-arity 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-hoist-variables 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-optimise-call-expression 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-regex 6.26.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-remap-async-to-generator 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helper-replace-supers 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-helpers 6.24.1 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-messages 6.23.0 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-check-es2015-constants 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-async-functions 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-async-generators 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-class-constructor-call 6.18.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-class-properties 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-decorators 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-do-expressions 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-dynamic-import 6.18.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-exponentiation-operator 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-export-extensions 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-function-bind 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-object-rest-spread 6.13.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-syntax-trailing-function-commas 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-async-generator-functions 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-async-to-generator 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-class-constructor-call 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-class-properties 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-decorators 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-do-expressions 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-arrow-functions 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-block-scoped-functions 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-block-scoping 6.26.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-classes 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-computed-properties 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-destructuring 6.23.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-duplicate-keys 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-for-of 6.23.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-function-name 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-literals 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-modules-amd 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-modules-commonjs 6.26.2 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-modules-systemjs 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-modules-umd 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-object-super 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-parameters 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-shorthand-properties 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-spread 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-sticky-regex 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-template-literals 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-typeof-symbol 6.23.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-es2015-unicode-regex 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-exponentiation-operator 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-export-extensions 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-function-bind 6.22.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-object-rest-spread 6.26.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-regenerator 6.26.0 - MIT -https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-regenerator - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-plugin-transform-strict-mode 6.24.1 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-preset-es2015 6.24.1 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-preset-stage-0 6.24.1 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-preset-stage-1 6.24.1 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-preset-stage-2 6.24.1 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-preset-stage-3 6.24.1 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-register 6.26.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-runtime 6.26.0 - MIT - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-template 6.26.0 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-traverse 6.26.0 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babel-types 6.26.0 - MIT -https://babeljs.io/ - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -babylon 6.18.0 - MIT -https://babeljs.io/ -Copyright (c) Mathias Bynens -Copyright (c) 2012-2014 by various contributors - -Copyright (C) 2012-2014 by various contributors (see AUTHORS) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -balanced-match 1.0.0 - MIT -https://github.com/juliangruber/balanced-match -Copyright (c) 2013 Julian Gruber - -(MIT) - -Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -base 0.11.2 - MIT -https://github.com/node-base/base -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -basic-auth 2.0.1 - MIT -https://github.com/jshttp/basic-auth#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2013 TJ Holowaychuk -Copyright (c) 2015-2016 Douglas Christopher Wilson -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015-2016 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2013 TJ Holowaychuk -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015-2016 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -bl 3.0.0 - MIT -https://github.com/rvagg/bl -Copyright (c) 2013-2018 bl contributors - -The MIT License (MIT) -===================== - -Copyright (c) 2013-2018 bl contributors ----------------------------------- - -*bl contributors listed at * - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -bluebird 3.5.5 - MIT -https://github.com/petkaantonov/bluebird -Copyright (c) 2013-2017 Petka Antonov -Copyright (c) 2013-2018 Petka Antonov - -The MIT License (MIT) - -Copyright (c) 2013-2018 Petka Antonov - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -body-parser 1.19.0 - MIT -https://github.com/expressjs/body-parser#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -brace-expansion 1.1.11 - MIT -https://github.com/juliangruber/brace-expansion -Copyright (c) 2013 Julian Gruber - -MIT License - -Copyright (c) 2013 Julian Gruber - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -braces 2.3.2 - MIT -https://github.com/micromatch/braces -Copyright (c) 2014-2018, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2018, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -buffer-crc32 0.2.13 - MIT -https://github.com/brianloveswords/buffer-crc32 -Copyright (c) 2013 Brian J. Brennan - -The MIT License - -Copyright (c) 2013 Brian J. Brennan - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -buffer-from 1.1.1 - MIT -https://github.com/LinusU/buffer-from#readme -Copyright (c) 2016, 2018 Linus Unneback - -MIT License - -Copyright (c) 2016, 2018 Linus Unnebäck - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -builtin-modules 1.1.1 - MIT -https://github.com/sindresorhus/builtin-modules#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -bytes 3.1.0 - MIT -https://github.com/visionmedia/bytes.js#readme -Copyright (c) 2015 Jed Watson -Copyright (c) 2012-2014 TJ Holowaychuk -Copyright (c) 2015 Jed Watson -Copyright (c) 2012-2014 TJ Holowaychuk - -(The MIT License) - -Copyright (c) 2012-2014 TJ Holowaychuk -Copyright (c) 2015 Jed Watson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cache-base 1.0.1 - MIT -https://github.com/jonschlinkert/cache-base -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -caller-callsite 2.0.0 - MIT -https://github.com/sindresorhus/caller-callsite#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -caller-path 2.0.0 - MIT -https://github.com/sindresorhus/caller-path#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -callsites 2.0.0 - MIT -https://github.com/sindresorhus/callsites#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -camelcase 5.0.0 - MIT -https://github.com/sindresorhus/camelcase#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cardinal 2.1.1 - MIT -https://github.com/thlorenz/cardinal#readme -Copyright 2012 Thorsten Lorenz. - -Copyright 2012 Thorsten Lorenz. -All rights reserved. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -chalk 1.1.3 - MIT -https://github.com/chalk/chalk#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -chalk 2.4.2 - MIT -https://github.com/chalk/chalk#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cheerio 1.0.0-rc.3 - MIT -https://github.com/cheeriojs/cheerio#readme -Copyright (c) 2016 Matt Mueller - -MIT License - -Copyright (c) 2016 Matt Mueller - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ci-info 2.0.0 - MIT -https://github.com/watson/ci-info -Copyright (c) 2016-2018 Thomas Watson Steen - -The MIT License (MIT) - -Copyright (c) 2016-2018 Thomas Watson Steen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -class-utils 0.3.6 - MIT -https://github.com/jonschlinkert/class-utils -Copyright (c) 2015, 2017-2018, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015, 2017-2018, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cli-cursor 2.1.0 - MIT -https://github.com/sindresorhus/cli-cursor#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cli-truncate 0.2.1 - MIT -https://github.com/sindresorhus/cli-truncate -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -code-point-at 1.1.0 - MIT -https://github.com/sindresorhus/code-point-at#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -collection-visit 1.0.0 - MIT -https://github.com/jonschlinkert/collection-visit -Copyright (c) 2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015, 2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -color 3.0.0 - MIT -https://github.com/Qix-/color#readme -Copyright (c) 2012 Heather Arthur - -Copyright (c) 2012 Heather Arthur - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -color-convert 1.9.3 - MIT -https://github.com/Qix-/color-convert#readme -Copyright (c) 2011-2016, Heather Arthur and Josh Junon. -Copyright (c) 2011-2016 Heather Arthur - -Copyright (c) 2011-2016 Heather Arthur - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -color-name 1.1.3 - MIT -https://github.com/dfcreative/color-name -Copyright (c) 2015 Dmitry Ivanov - -The MIT License (MIT) -Copyright (c) 2015 Dmitry Ivanov - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -color-string 1.5.3 - MIT -https://github.com/Qix-/color-string#readme -Copyright (c) 2011 Heather Arthur - -Copyright (c) 2011 Heather Arthur - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -colornames 1.1.1 - MIT -https://github.com/timoxley/colornames#readme -Copyright (c) 2015 Tim Oxley - -The MIT License (MIT) - -Copyright (c) 2015 Tim Oxley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -colors 1.3.3 - MIT -https://github.com/Marak/colors.js -Copyright (c) Marak Squires -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Original Library - - Copyright (c) Marak Squires - -Additional Functionality - - Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -colorspace 1.1.2 - MIT -https://github.com/3rd-Eden/colorspace -Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman - -The MIT License (MIT) - -Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -combined-stream 1.0.8 - MIT -https://github.com/felixge/node-combined-stream -Copyright (c) 2011 Debuggable Limited - -Copyright (c) 2011 Debuggable Limited - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -commander 2.20.0 - MIT -https://github.com/tj/commander.js#readme -Copyright (c) 2011 TJ Holowaychuk - -(The MIT License) - -Copyright (c) 2011 TJ Holowaychuk - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -commander 2.15.1 - MIT -https://github.com/tj/commander.js#readme -Copyright (c) 2011 TJ Holowaychuk - -(The MIT License) - -Copyright (c) 2011 TJ Holowaychuk - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -component-emitter 1.3.0 - MIT -https://github.com/component/emitter#readme -Copyright (c) 2014 Component - -(The MIT License) - -Copyright (c) 2014 Component contributors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -concat-map 0.0.1 - MIT -https://github.com/substack/node-concat-map - -This software is released under the MIT license: - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -content-disposition 0.5.3 - MIT -https://github.com/jshttp/content-disposition#readme -Copyright (c) 2014-2017 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2014-2017 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -content-type 1.0.4 - MIT -https://github.com/jshttp/content-type#readme -Copyright (c) 2015 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -convert-source-map 1.6.0 - MIT -https://github.com/thlorenz/convert-source-map -Copyright 2013 Thorsten Lorenz. - -Copyright 2013 Thorsten Lorenz. -All rights reserved. - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cookie 0.4.0 - MIT -https://github.com/jshttp/cookie#readme -Copyright (c) 2012-2014 Roman Shtylman -Copyright (c) 2015 Douglas Christopher Wilson -Copyright (c) 2012-2014 Roman Shtylman -Copyright (c) 2015 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2012-2014 Roman Shtylman -Copyright (c) 2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cookie-signature 1.0.6 - MIT -https://github.com/visionmedia/node-cookie-signature -Copyright (c) 2012 LearnBoost - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -copy-descriptor 0.1.1 - MIT -https://github.com/jonschlinkert/copy-descriptor -Copyright (c) 2015, Jon Schlinkert. -Copyright (c) 2015-2016, Jon Schlinkert - -The MIT License (MIT) - -Copyright (c) 2015-2016, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -core-js 2.6.9 - MIT -https://github.com/zloirock/core-js#readme -(c) 2019 Denis Pushkarev -copyright (c) 2019 Denis Pushkarev -Copyright (c) 2014-2019 Denis Pushkarev - -Copyright (c) 2014-2019 Denis Pushkarev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -core-util-is 1.0.2 - MIT -https://github.com/isaacs/core-util-is#readme -Copyright Joyent, Inc. and other Node contributors. - -Copyright Node.js contributors. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cosmiconfig 5.2.1 - MIT -https://github.com/davidtheclark/cosmiconfig#readme -Copyright (c) 2015 David Clark - -The MIT License (MIT) - -Copyright (c) 2015 David Clark - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cross-env 6.0.3 - MIT -https://github.com/kentcdodds/cross-env#readme -Copyright (c) 2017 Kent C. Dodds - -The MIT License (MIT) -Copyright (c) 2017 Kent C. Dodds - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cross-spawn 5.1.0 - MIT -https://github.com/IndigoUnited/node-cross-spawn#readme -Copyright (c) 2014 IndigoUnited - -Copyright (c) 2014 IndigoUnited - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cross-spawn 7.0.1 - MIT -https://github.com/moxystudio/node-cross-spawn -Copyright (c) 2018 Made With MOXY Lda - -The MIT License (MIT) - -Copyright (c) 2018 Made With MOXY Lda - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cross-spawn 6.0.5 - MIT -https://github.com/moxystudio/node-cross-spawn -Copyright (c) 2018 Made With MOXY Lda - -The MIT License (MIT) - -Copyright (c) 2018 Made With MOXY Lda - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -cross-var 1.1.0 - MIT -https://github.com/elijahmanor/cross-var#readme -Copyright (c) 2016 Elijah Manor - -MIT License - -Copyright (c) 2016 Elijah Manor - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -dashdash 1.14.1 - MIT -https://github.com/trentm/node-dashdash#readme -Copyright 2016 Trent Mick -Copyright 2016 Joyent, Inc. -Copyright (c) 2013 Joyent Inc. -Copyright (c) 2013 Trent Mick. - -# This is the MIT license - -Copyright (c) 2013 Trent Mick. All rights reserved. -Copyright (c) 2013 Joyent Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -date-fns 1.30.1 - MIT -https://github.com/date-fns/date-fns#readme -(c) Sasha Koss (https://kossnocorp.mit-license.org/) - -# License - -date-fns is licensed under the [MIT license](http://kossnocorp.mit-license.org). -Read more about MIT at [TLDRLegal](https://tldrlegal.com/license/mit-license). - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -date-utils 1.2.21 - MIT -https://jerrysievert.github.io/date-utils/ -(c) 2011 by Jerry Sievert -Copyright 2012 Twitter, Inc. -Copyright 2013 Twitter, Inc. -(c) 2005, 2013 jQuery Foundation, Inc. - -© 2011 by Jerry Sievert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -debug 3.1.0 - MIT -https://github.com/visionmedia/debug#readme -Copyright (c) 2014 TJ Holowaychuk -Copyright (c) 2014-2017 TJ Holowaychuk - -(The MIT License) - -Copyright (c) 2014 TJ Holowaychuk - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software -and associated documentation files (the 'Software'), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -debug 2.6.9 - MIT -https://github.com/visionmedia/debug#readme -Copyright (c) 2014 TJ Holowaychuk -Copyright (c) 2014-2016 TJ Holowaychuk - -(The MIT License) - -Copyright (c) 2014 TJ Holowaychuk - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software -and associated documentation files (the 'Software'), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -debug 4.1.1 - MIT -https://github.com/visionmedia/debug#readme -Copyright (c) 2014 TJ Holowaychuk -Copyright (c) 2014-2017 TJ Holowaychuk - -(The MIT License) - -Copyright (c) 2014 TJ Holowaychuk - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software -and associated documentation files (the 'Software'), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -decode-uri-component 0.2.0 - MIT -https://github.com/samverschueren/decode-uri-component#readme -(c) Sam Verschueren (https://github.com/SamVerschueren) -Copyright (c) Sam Verschueren - -The MIT License (MIT) - -Copyright (c) Sam Verschueren (github.com/SamVerschueren) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -dedent 0.7.0 - MIT -https://github.com/dmnd/dedent -Copyright (c) 2015 Desmond Brand (dmnd@desmondbrand.com) - -The MIT License (MIT) - -Copyright (c) 2015 Desmond Brand (dmnd@desmondbrand.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -define-properties 1.1.3 - MIT -https://github.com/ljharb/define-properties#readme -Copyright (c) 2015 Jordan Harband - -The MIT License (MIT) - -Copyright (C) 2015 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -define-property 2.0.2 - MIT -https://github.com/jonschlinkert/define-property -Copyright (c) 2015-2018, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2018, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -define-property 0.2.5 - MIT -https://github.com/jonschlinkert/define-property -Copyright (c) 2015 Jon Schlinkert -Copyright (c) 2015, Jon Schlinkert. - -The MIT License (MIT) - -Copyright (c) 2015, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -define-property 1.0.0 - MIT -https://github.com/jonschlinkert/define-property -Copyright (c) 2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015, 2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -del 3.0.0 - MIT -https://github.com/sindresorhus/del#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -delayed-stream 1.0.0 - MIT -https://github.com/felixge/node-delayed-stream -Copyright (c) 2011 Debuggable Limited - -Copyright (c) 2011 Debuggable Limited - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -denodeify 1.2.1 - MIT -https://github.com/matthew-andrews/denodeify - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -depd 1.1.2 - MIT -https://github.com/dougwilson/nodejs-depd#readme -Copyright (c) 2014 Douglas Christopher Wilson -Copyright (c) 2015 Douglas Christopher Wilson -Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) 2014-2017 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2014-2017 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -depd 2.0.0 - MIT -https://github.com/dougwilson/nodejs-depd#readme -Copyright (c) 2015 Douglas Christopher Wilson -Copyright (c) 2014-2018 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2014-2018 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -destroy 1.0.4 - MIT -https://github.com/stream-utils/destroy -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014 Jonathan Ong me@jongleberry.com - - -The MIT License (MIT) - -Copyright (c) 2014 Jonathan Ong me@jongleberry.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -detect-indent 4.0.0 - MIT -https://github.com/sindresorhus/detect-indent -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -diagnostics 1.1.1 - MIT -https://github.com/bigpipe/diagnostics -Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman - -The MIT License (MIT) - -Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -dom-serializer 0.1.1 - MIT -https://github.com/cheeriojs/dom-renderer#readme -Copyright (c) 2014 - -License - -(The MIT License) - -Copyright (c) 2014 The cheeriojs contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -dottie 2.0.1 - MIT -https://github.com/mickhansen/dottie.js#readme -Copyright (c) 2013-2014 Mick Hansen. http://mhansen.io - -The MIT License - -Copyright (c) 2013-2014 Mick Hansen. http://mhansen.io - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ecc-jsbn 0.1.2 - MIT -https://github.com/quartzjer/ecc-jsbn -Copyright (c) 2003-2005 Tom Wu -Copyright (c) 2014 Jeremie Miller - -The MIT License (MIT) - -Copyright (c) 2014 Jeremie Miller - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ee-first 1.1.1 - MIT -https://github.com/jonathanong/ee-first -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014 Jonathan Ong me@jongleberry.com - - -The MIT License (MIT) - -Copyright (c) 2014 Jonathan Ong me@jongleberry.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -elegant-spinner 1.0.1 - MIT -https://github.com/sindresorhus/elegant-spinner -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -enabled 1.0.2 - MIT -https://github.com/bigpipe/enabled#readme -Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman - -The MIT License (MIT) - -Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -encodeurl 1.0.2 - MIT -https://github.com/pillarjs/encodeurl#readme -Copyright (c) 2016 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2016 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -end-of-stream 1.4.1 - MIT -https://github.com/mafintosh/end-of-stream -Copyright (c) 2014 Mathias Buus - -The MIT License (MIT) - -Copyright (c) 2014 Mathias Buus - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -env-variable 0.0.5 - MIT -https://github.com/3rd-Eden/env-variable -Copyright 2014 Arnout Kazemier - -Copyright 2014 Arnout Kazemier - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -error-ex 1.3.2 - MIT -https://github.com/qix-/node-error-ex#readme -Copyright (c) 2015 JD Ballard - -The MIT License (MIT) - -Copyright (c) 2015 JD Ballard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -es-abstract 1.14.2 - MIT -https://github.com/ljharb/es-abstract#readme -Copyright (c) 2015 Jordan Harband - -The MIT License (MIT) - -Copyright (C) 2015 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -es-to-primitive 1.2.0 - MIT -https://github.com/ljharb/es-to-primitive#readme -Copyright (c) 2015 Jordan Harband - -The MIT License (MIT) - -Copyright (c) 2015 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -escape-html 1.0.3 - MIT -https://github.com/component/escape-html -Copyright (c) 2015 Andreas Lubbe -Copyright (c) 2012-2013 TJ Holowaychuk -Copyright (c) 2015 Tiancheng Timothy Gu - -(The MIT License) - -Copyright (c) 2012-2013 TJ Holowaychuk -Copyright (c) 2015 Andreas Lubbe -Copyright (c) 2015 Tiancheng "Timothy" Gu - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -escape-string-regexp 1.0.5 - MIT -https://github.com/sindresorhus/escape-string-regexp -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -etag 1.8.1 - MIT -https://github.com/jshttp/etag#readme -Copyright (c) 2014-2016 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2014-2016 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -event-target-shim 5.0.1 - MIT -https://github.com/mysticatea/event-target-shim -copyright 2015 Toru Nagashima. -Copyright (c) 2015 Toru Nagashima - -The MIT License (MIT) - -Copyright (c) 2015 Toru Nagashima - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -events 3.0.0 - MIT -https://github.com/Gozala/events#readme -Copyright Joyent, Inc. and other Node contributors. - -MIT - -Copyright Joyent, Inc. and other Node contributors. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, subject to the -following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -execa 1.0.0 - MIT -https://github.com/sindresorhus/execa#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -exit 0.1.2 - MIT -https://github.com/cowboy/node-exit -Copyright (c) 2013 Cowboy Ben Alman - -Copyright (c) 2013 "Cowboy" Ben Alman - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -expand-brackets 2.1.4 - MIT -https://github.com/jonschlinkert/expand-brackets -Copyright (c) 2015-2016, Jon Schlinkert -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2016, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -express 4.17.1 - MIT -http://expressjs.com/ -Copyright (c) 2013 Roman Shtylman -Copyright (c) 2009-2013 TJ Holowaychuk -Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) 2009-2014 TJ Holowaychuk -Copyright (c) 2013-2014 Roman Shtylman -Copyright (c) 2014-2015 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2009-2014 TJ Holowaychuk -Copyright (c) 2013-2014 Roman Shtylman -Copyright (c) 2014-2015 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -extend 3.0.2 - MIT -https://github.com/justmoon/node-extend#readme -Copyright (c) 2014 Stefan Thomas - -The MIT License (MIT) - -Copyright (c) 2014 Stefan Thomas - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -extend-shallow 3.0.2 - MIT -https://github.com/jonschlinkert/extend-shallow -Copyright (c) 2014-2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2015, 2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -extend-shallow 2.0.1 - MIT -https://github.com/jonschlinkert/extend-shallow -Copyright (c) 2015 Jon Schlinkert -Copyright (c) 2014-2015, Jon Schlinkert. - -The MIT License (MIT) - -Copyright (c) 2014-2015, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -extglob 2.0.4 - MIT -https://github.com/micromatch/extglob -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -extsprintf 1.3.0 - MIT -https://github.com/davepacheco/node-extsprintf -Copyright (c) 2012, Joyent, Inc. - -Copyright (c) 2012, Joyent, Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fast-deep-equal 2.0.1 - MIT -https://github.com/epoberezkin/fast-deep-equal#readme -Copyright (c) 2017 Evgeny Poberezkin - -MIT License - -Copyright (c) 2017 Evgeny Poberezkin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fast-json-stable-stringify 2.1.0 - MIT -https://github.com/epoberezkin/fast-json-stable-stringify -Copyright (c) 2013 James Halliday -Copyright (c) 2017 Evgeny Poberezkin - -This software is released under the MIT license: - -Copyright (c) 2017 Evgeny Poberezkin -Copyright (c) 2013 James Halliday - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fast-safe-stringify 2.0.7 - MIT -https://github.com/davidmarkclements/fast-safe-stringify#readme -Copyright (c) 2016 David Mark Clements -Copyright (c) 2017 David Mark Clements & Matteo Collina -Copyright (c) 2018 David Mark Clements, Matteo Collina & Ruben Bridgewater - -The MIT License (MIT) - -Copyright (c) 2016 David Mark Clements -Copyright (c) 2017 David Mark Clements & Matteo Collina -Copyright (c) 2018 David Mark Clements, Matteo Collina & Ruben Bridgewater - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fd-slicer 1.1.0 - MIT -https://github.com/andrewrk/node-fd-slicer#readme -Copyright (c) 2014 Andrew Kelley - -Copyright (c) 2014 Andrew Kelley - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation files -(the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fecha 2.3.3 - MIT -https://github.com/taylorhakes/fecha -Copyright (c) 2015 Taylor Hakes - -The MIT License (MIT) - -Copyright (c) 2015 Taylor Hakes - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -figures 2.0.0 - MIT -https://github.com/sindresorhus/figures#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -figures 1.7.0 - MIT -https://github.com/sindresorhus/figures#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fill-range 4.0.0 - MIT -https://github.com/jonschlinkert/fill-range -Copyright (c) 2014-2017, Jon Schlinkert -Copyright (c) 2014-2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -finalhandler 1.1.2 - MIT -https://github.com/pillarjs/finalhandler#readme -Copyright (c) 2014-2017 Douglas Christopher Wilson -Copyright (c) 2014-2017 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2014-2017 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -find-up 3.0.0 - MIT -https://github.com/sindresorhus/find-up#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fn-name 2.0.1 - MIT -https://github.com/sindresorhus/fn-name -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -follow-redirects 1.5.10 - MIT -https://github.com/follow-redirects/follow-redirects -Copyright 2014-present Olivier Lalonde , James Talmage , Ruben Verborgh - -Copyright 2014–present Olivier Lalonde , James Talmage , Ruben Verborgh - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -for-in 1.0.2 - MIT -https://github.com/jonschlinkert/for-in -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -form-data 2.3.3 - MIT -https://github.com/form-data/form-data#readme -Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors - -Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -form-data 2.5.1 - MIT -https://github.com/form-data/form-data#readme -Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors - -Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -forwarded 0.1.2 - MIT -https://github.com/jshttp/forwarded#readme -Copyright (c) 2014-2017 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2014-2017 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fragment-cache 0.2.1 - MIT -https://github.com/jonschlinkert/fragment-cache -Copyright (c) 2016-2017, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2016-2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -fresh 0.5.2 - MIT -https://github.com/jshttp/fresh#readme -Copyright (c) 2012 TJ Holowaychuk -Copyright (c) 2016-2017 Douglas Christopher Wilson -Copyright (c) 2012 TJ Holowaychuk -Copyright (c) 2016-2017 Douglas Christopher Wilson - -(The MIT License) - -Copyright (c) 2012 TJ Holowaychuk -Copyright (c) 2016-2017 Douglas Christopher Wilson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -function-bind 1.1.1 - MIT -https://github.com/Raynos/function-bind -Copyright (c) 2013 Raynos. - -Copyright (c) 2013 Raynos. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -g-status 2.0.2 - MIT -https://github.com/luftywiranda13/g-status#readme -(c) Lufty Wiranda (https://www.luftywiranda.com) -Copyright (c) Lufty Wiranda - -MIT License - -Copyright (c) Lufty Wiranda - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -generate-function 2.3.1 - MIT -https://github.com/mafintosh/generate-function -Copyright (c) 2014 Mathias Buus - -The MIT License (MIT) - -Copyright (c) 2014 Mathias Buus - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -get-stdin 6.0.0 - MIT -https://github.com/sindresorhus/get-stdin#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -get-stream 4.1.0 - MIT -https://github.com/sindresorhus/get-stream#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -get-value 2.0.6 - MIT -https://github.com/jonschlinkert/get-value -Copyright (c) 2014-2015, Jon Schlinkert. -Copyright (c) 2014-2016, Jon Schlinkert. - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -getpass 0.1.7 - MIT -https://github.com/arekinath/node-getpass#readme -Copyright Joyent, Inc. -Copyright 2016, Joyent, Inc. - -Copyright Joyent, Inc. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -globals 9.18.0 - MIT -https://github.com/sindresorhus/globals#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -globby 6.1.0 - MIT -https://github.com/sindresorhus/globby#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -growl 1.10.5 - MIT -https://github.com/tj/node-growl#readme -Copyright TJ Holowaychuk -Copyright (c) 2009 TJ Holowaychuk -Copyright (c) 2016 Joshua Boy Nicolai Appelman - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -har-validator 5.1.3 - MIT -https://github.com/ahmadnassri/node-har-validator -Copyright (c) 2018 Ahmad Nassri - -MIT License - -Copyright (c) 2018 Ahmad Nassri - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -has 1.0.3 - MIT -https://github.com/tarruda/has -Copyright (c) 2013 Thiago de Arruda - -Copyright (c) 2013 Thiago de Arruda - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -has-ansi 2.0.0 - MIT -https://github.com/sindresorhus/has-ansi -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -has-flag 3.0.0 - MIT -https://github.com/sindresorhus/has-flag#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -has-symbols 1.0.0 - MIT -https://github.com/ljharb/has-symbols#readme -Copyright (c) 2016 Jordan Harband - -MIT License - -Copyright (c) 2016 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -has-value 0.3.1 - MIT -https://github.com/jonschlinkert/has-value -Copyright (c) 2014-2016, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -has-value 1.0.0 - MIT -https://github.com/jonschlinkert/has-value -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -has-values 1.0.0 - MIT -https://github.com/jonschlinkert/has-values -Copyright (c) 2014-2017, Jon Schlinkert -Copyright (c) 2014-2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -has-values 0.1.4 - MIT -https://github.com/jonschlinkert/has-values -Copyright (c) 2014-2015, Jon Schlinkert. -Copyright (c) 2014-2016, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -he 1.1.1 - MIT -https://mths.be/he -Copyright Mathias Bynens - -Copyright Mathias Bynens - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -home-or-tmp 2.0.0 - MIT -https://github.com/sindresorhus/home-or-tmp -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -htmlparser2 3.10.1 - MIT -https://github.com/fb55/htmlparser2#readme -Copyright 2010, 2011, Chris Winberry - -Copyright 2010, 2011, Chris Winberry . All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -http-errors 1.7.2 - MIT -https://github.com/jshttp/http-errors#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2016 Douglas Christopher Wilson -Copyright (c) 2014 Jonathan Ong me@jongleberry.com -Copyright (c) 2016 Douglas Christopher Wilson doug@somethingdoug.com - - -The MIT License (MIT) - -Copyright (c) 2014 Jonathan Ong me@jongleberry.com -Copyright (c) 2016 Douglas Christopher Wilson doug@somethingdoug.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -http-signature 1.2.0 - MIT -https://github.com/joyent/node-http-signature/ -Copyright Joyent, Inc. -Copyright 2012 Joyent, Inc. -Copyright 2015 Joyent, Inc. -Copyright (c) 2011 Joyent, Inc. - -Copyright Joyent, Inc. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -husky 1.3.1 - MIT -https://github.com/typicode/husky#readme -Copyright (c) 2017 - -MIT License - -Copyright (c) 2017 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -iconv-lite 0.5.0 - MIT -https://github.com/ashtuchkin/iconv-lite -Copyright (c) Microsoft Corporation. -Copyright (c) 2011 Alexander Shtuchkin - -Copyright (c) 2011 Alexander Shtuchkin - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -iconv-lite 0.4.24 - MIT -https://github.com/ashtuchkin/iconv-lite -Copyright (c) Microsoft Corporation. -Copyright (c) 2011 Alexander Shtuchkin - -Copyright (c) 2011 Alexander Shtuchkin - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -import-fresh 2.0.0 - MIT -https://github.com/sindresorhus/import-fresh#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -indent-string 3.2.0 - MIT -https://github.com/sindresorhus/indent-string#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -inflection 1.12.0 - MIT -https://github.com/dreamerslab/node.inflection#readme -Copyright (c) 2011 -Copyright (c) 2011 Ben Lin - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -invariant 2.2.4 - MIT -https://github.com/zertosh/invariant#readme -Copyright (c) 2013-present, Facebook, Inc. - -MIT License - -Copyright (c) 2013-present, Facebook, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ip-regex 2.1.0 - MIT -https://github.com/sindresorhus/ip-regex#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -ipaddr.js 1.9.0 - MIT -https://github.com/whitequark/ipaddr.js#readme -Copyright (c) 2011-2017 - -Copyright (C) 2011-2017 whitequark - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-accessor-descriptor 1.0.0 - MIT -https://github.com/jonschlinkert/is-accessor-descriptor -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-accessor-descriptor 0.1.6 - MIT -https://github.com/jonschlinkert/is-accessor-descriptor -Copyright (c) 2015, Jon Schlinkert. -Copyright (c) 2015 Jon Schlinkert (https://github.com/jonschlinkert) - -The MIT License (MIT) - -Copyright (c) 2015, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-arrayish 0.3.2 - MIT -https://github.com/qix-/node-is-arrayish#readme -Copyright (c) 2015 JD Ballard - -The MIT License (MIT) - -Copyright (c) 2015 JD Ballard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-arrayish 0.2.1 - MIT -https://github.com/qix-/node-is-arrayish#readme -Copyright (c) 2015 JD Ballard - -The MIT License (MIT) - -Copyright (c) 2015 JD Ballard - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-bluebird 1.0.2 - MIT -https://github.com/overlookmotel/is-bluebird#readme -Copyright (c) 2016 Overlook Motel (theoverlookmotel@gmail.com) - -Copyright (c) 2016 Overlook Motel (theoverlookmotel@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-buffer 1.1.6 - MIT -https://github.com/feross/is-buffer#readme -Copyright (c) Feross Aboukhadijeh -Copyright (c) Feross Aboukhadijeh (http://feross.org). - -The MIT License (MIT) - -Copyright (c) Feross Aboukhadijeh - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-buffer 2.0.3 - MIT -https://github.com/feross/is-buffer#readme -Copyright (c) Feross Aboukhadijeh -Copyright (c) Feross Aboukhadijeh (http://feross.org). - -The MIT License (MIT) - -Copyright (c) Feross Aboukhadijeh - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-callable 1.1.4 - MIT -https://github.com/ljharb/is-callable#readme -Copyright (c) 2015 Jordan Harband - -The MIT License (MIT) - -Copyright (c) 2015 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-ci 2.0.0 - MIT -https://github.com/watson/is-ci -Copyright (c) 2016-2018 Thomas Watson Steen - -The MIT License (MIT) - -Copyright (c) 2016-2018 Thomas Watson Steen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-data-descriptor 0.1.4 - MIT -https://github.com/jonschlinkert/is-data-descriptor -Copyright (c) 2015, Jon Schlinkert. -Copyright (c) 2015 Jon Schlinkert (https://github.com/jonschlinkert) - -The MIT License (MIT) - -Copyright (c) 2015, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-data-descriptor 1.0.0 - MIT -https://github.com/jonschlinkert/is-data-descriptor -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-date-object 1.0.1 - MIT -https://github.com/ljharb/is-date-object#readme -Copyright (c) 2015 Jordan Harband - -The MIT License (MIT) - -Copyright (c) 2015 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-descriptor 1.0.2 - MIT -https://github.com/jonschlinkert/is-descriptor -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-descriptor 0.1.6 - MIT -https://github.com/jonschlinkert/is-descriptor -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-directory 0.3.1 - MIT -https://github.com/jonschlinkert/is-directory -Copyright (c) 2014-2015, Jon Schlinkert. -Copyright (c) 2014-2016, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-extendable 1.0.1 - MIT -https://github.com/jonschlinkert/is-extendable -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-extendable 0.1.1 - MIT -https://github.com/jonschlinkert/is-extendable -Copyright (c) 2015 Jon Schlinkert -Copyright (c) 2015, Jon Schlinkert. - -The MIT License (MIT) - -Copyright (c) 2015, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-extglob 2.1.1 - MIT -https://github.com/jonschlinkert/is-extglob -Copyright (c) 2014-2016, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-finite 1.0.2 - MIT -https://github.com/sindresorhus/is-finite#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-fullwidth-code-point 2.0.0 - MIT -https://github.com/sindresorhus/is-fullwidth-code-point#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-fullwidth-code-point 1.0.0 - MIT -https://github.com/sindresorhus/is-fullwidth-code-point -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-glob 4.0.1 - MIT -https://github.com/micromatch/is-glob -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2019, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-number 3.0.0 - MIT -https://github.com/jonschlinkert/is-number -Copyright (c) 2014-2016, Jon Schlinkert -Copyright (c) 2014-2015, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-obj 1.0.1 - MIT -https://github.com/sindresorhus/is-obj#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-observable 1.1.0 - MIT -https://github.com/sindresorhus/is-observable#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-path-cwd 1.0.0 - MIT -https://github.com/sindresorhus/is-path-cwd -(c) Sindre Sorhus (http://sindresorhus.com) - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-path-in-cwd 1.0.1 - MIT -https://github.com/sindresorhus/is-path-in-cwd#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-path-inside 1.0.1 - MIT -https://github.com/sindresorhus/is-path-inside#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-plain-object 2.0.4 - MIT -https://github.com/jonschlinkert/is-plain-object -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-promise 2.1.0 - MIT -https://github.com/then/is-promise -Copyright (c) 2014 Forbes Lindesay - -Copyright (c) 2014 Forbes Lindesay - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-property 1.0.2 - MIT -https://github.com/mikolalysenko/is-property -(c) 2013 Mikola Lysenko. -Copyright (c) 2013 Mikola Lysenko - - -The MIT License (MIT) - -Copyright (c) 2013 Mikola Lysenko - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-regex 1.0.4 - MIT -https://github.com/ljharb/is-regex -Copyright (c) 2014 Jordan Harband - -The MIT License (MIT) - -Copyright (c) 2014 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-regexp 1.0.0 - MIT -https://github.com/sindresorhus/is-regexp -(c) Sindre Sorhus (http://sindresorhus.com) - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-stream 1.1.0 - MIT -https://github.com/sindresorhus/is-stream#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-symbol 1.0.2 - MIT -https://github.com/ljharb/is-symbol#readme -Copyright (c) 2015 Jordan Harband - -The MIT License (MIT) - -Copyright (c) 2015 Jordan Harband - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-typedarray 1.0.0 - MIT -https://github.com/hughsk/is-typedarray - -This software is released under the MIT license: - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -is-windows 1.0.2 - MIT -https://github.com/jonschlinkert/is-windows -Copyright (c) 2015-2018, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2018, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -isarray 1.0.0 - MIT -https://github.com/juliangruber/isarray -Copyright (c) 2013 Julian Gruber - -MIT License - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -isobject 3.0.1 - MIT -https://github.com/jonschlinkert/isobject -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -isobject 2.1.0 - MIT -https://github.com/jonschlinkert/isobject -Copyright (c) 2014-2015, Jon Schlinkert. -Copyright (c) 2014-2016, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2016, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -isstream 0.1.2 - MIT -https://github.com/rvagg/isstream -Copyright (c) 2015 Rod Vagg -Copyright (c) 2015 Rod Vagg rvagg (https://twitter.com/rvagg) - -The MIT License (MIT) -===================== - -Copyright (c) 2015 Rod Vagg ---------------------------- - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -js-tokens 4.0.0 - MIT -https://github.com/lydell/js-tokens#readme -Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell -Copyright (c) 2014, 2015, 2016, 2017, 2018 Simon Lydell - -The MIT License (MIT) - -Copyright (c) 2014, 2015, 2016, 2017, 2018 Simon Lydell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -js-tokens 3.0.2 - MIT -https://github.com/lydell/js-tokens#readme -Copyright 2014, 2015, 2016, 2017 Simon Lydell -Copyright (c) 2014, 2015, 2016, 2017 Simon Lydell - -The MIT License (MIT) - -Copyright (c) 2014, 2015, 2016, 2017 Simon Lydell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -js-yaml 3.13.1 - MIT -https://github.com/nodeca/js-yaml -Copyright (c) 2011-2015 by Vitaly Puzrin - -(The MIT License) - -Copyright (C) 2011-2015 by Vitaly Puzrin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -jsbn 0.1.1 - MIT -https://github.com/andyperlitch/jsbn#readme -Copyright (c) 2005 Tom Wu -Copyright (c) 2003-2005 Tom Wu -Copyright (c) 2005-2009 Tom Wu - -Licensing ---------- - -This software is covered under the following copyright: - -/* - * Copyright (c) 2003-2005 Tom Wu - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF - * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * In addition, the following condition applies: - * - * All redistributions must retain an intact copy of this copyright notice - * and disclaimer. - */ - -Address all questions regarding this license to: - - Tom Wu - tjw@cs.Stanford.EDU - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -jsesc 1.3.0 - MIT -https://mths.be/jsesc -Copyright Mathias Bynens - -Copyright Mathias Bynens - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -jsesc 0.5.0 - MIT -http://mths.be/jsesc -Copyright Mathias Bynens - -Copyright Mathias Bynens - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -json-parse-better-errors 1.0.2 - MIT -https://github.com/zkat/json-parse-better-errors#readme -Copyright 2017 Kat Marchan - -Copyright 2017 Kat Marchán - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -json-schema-traverse 0.4.1 - MIT -https://github.com/epoberezkin/json-schema-traverse#readme -Copyright (c) 2017 Evgeny Poberezkin - -MIT License - -Copyright (c) 2017 Evgeny Poberezkin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -json5 0.5.1 - MIT -http://json5.org/ -Copyright (c) 2012-2016 Aseem Kishore, and others (https://github.com/aseemk/json5/contributors). - -MIT License - -Copyright (c) 2012-2016 Aseem Kishore, and [others](https://github.com/aseemk/json5/contributors). - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -jsonwebtoken 8.5.1 - MIT -https://github.com/auth0/node-jsonwebtoken#readme -Copyright (c) 2015 Auth0, Inc. (http://auth0.com) - -The MIT License (MIT) - -Copyright (c) 2015 Auth0, Inc. (http://auth0.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -jsprim 1.4.1 - MIT -https://github.com/joyent/node-jsprim#readme -Copyright (c) 2012, Joyent, Inc. - -Copyright (c) 2012, Joyent, Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -jwa 1.4.1 - MIT -https://github.com/brianloveswords/node-jwa#readme -Copyright (c) 2013 Brian J. Brennan - -Copyright (c) 2013 Brian J. Brennan - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -jws 3.2.2 - MIT -https://github.com/brianloveswords/node-jws#readme -Copyright (c) 2013 Brian J. Brennan -Copyright (c) 2013-2015 Brian J. Brennan - -Copyright (c) 2013 Brian J. Brennan - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -kind-of 5.1.0 - MIT -https://github.com/jonschlinkert/kind-of -Copyright (c) 2014-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -kind-of 3.2.2 - MIT -https://github.com/jonschlinkert/kind-of -Copyright (c) 2014-2017, Jon Schlinkert -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -kind-of 4.0.0 - MIT -https://github.com/jonschlinkert/kind-of -Copyright (c) 2014-2017, Jon Schlinkert -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2014-2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Copyright (c) 2016, Philipp Thürwächter & Pattrick Hüper + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of js-joda nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -kuler 1.0.1 - MIT -https://github.com/3rd-Eden/kuler -Copyright 2014 Arnout Kazemier +--------------------------------------------------------- -Copyright 2014 Arnout Kazemier +bcrypt-pbkdf 1.0.2 - BSD-3-Clause +https://github.com/joyent/node-bcrypt-pbkdf#readme -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright 2016, Joyent Inc +Copyright (c) 2013 Ted Unangst +Copyright 1997 Niels Provos -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The Blowfish portions are under the following license: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Blowfish block cipher for OpenBSD +Copyright 1997 Niels Provos +All rights reserved. +Implementation advice by David Mazieres . -------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. -------------------------------------------------------------------- +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -leven 2.1.0 - MIT -https://github.com/sindresorhus/leven#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) -The MIT License (MIT) -Copyright (c) Sindre Sorhus (sindresorhus.com) +The bcrypt_pbkdf portions are under the following license: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2013 Ted Unangst -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +Performance improvements (Javascript-specific): -linkify-it 2.2.0 - MIT -https://github.com/markdown-it/linkify-it#readme -Copyright (c) 2015 Vitaly Puzrin. +Copyright 2016, Joyent Inc +Author: Alex Wilson -Copyright (c) 2015 Vitaly Puzrin. +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +buffer-equal-constant-time 1.0.1 - BSD-3-Clause -------------------------------------------------------------------- -lint-staged 8.2.1 - MIT -https://github.com/okonet/lint-staged#readme -Copyright (c) 2016 Andrey Okonetchnikov +(c) 2013 GoInstant Inc., a salesforce.com company +Copyright (c) 2013, GoInstant Inc., a salesforce.com company -The MIT License (MIT) +Copyright (c) 2013, GoInstant Inc., a salesforce.com company +All rights reserved. -Copyright (c) 2016 Andrey Okonetchnikov +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +* Neither the name of salesforce.com, nor GoInstant, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -listr 0.14.3 - MIT -https://github.com/SamVerschueren/listr#readme -(c) Sam Verschueren (https://github.com/SamVerschueren) -Copyright (c) Sam Verschueren +--------------------------------------------------------- -The MIT License (MIT) +qs 6.5.2 - BSD-3-Clause +https://github.com/ljharb/qs -Copyright (c) Sam Verschueren (github.com/SamVerschueren) +Copyright (c) 2014 Nathan LaFreniere and other contributors. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2014 Nathan LaFreniere and other contributors. +All rights reserved. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * * * -------------------------------------------------------------------- +The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors -------------------------------------------------------------------- -listr-silent-renderer 1.1.1 - MIT -https://github.com/samverschueren/listr-silent-renderer#readme -(c) Sam Verschueren (https://github.com/SamVerschueren) -Copyright (c) Sam Verschueren +--------------------------------------------------------- -The MIT License (MIT) +--------------------------------------------------------- -Copyright (c) Sam Verschueren (github.com/SamVerschueren) +qs 6.7.0 - BSD-3-Clause +https://github.com/ljharb/qs -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2014 Nathan LaFreniere and other contributors. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Copyright (c) 2014 Nathan LaFreniere and other contributors. +All rights reserved. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------- + * * * -------------------------------------------------------------------- +The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors -listr-update-renderer 0.5.0 - MIT -https://github.com/SamVerschueren/listr-update-renderer#readme -(c) Sam Verschueren (https://github.com/SamVerschueren) -Copyright (c) Sam Verschueren -The MIT License (MIT) +--------------------------------------------------------- -Copyright (c) Sam Verschueren (github.com/SamVerschueren) +--------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +sprintf-js 1.1.2 - BSD-3-Clause +https://github.com/alexei/sprintf.js#readme -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Copyright (c) 2007-present, Alexandru Marasteanu -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Copyright (c) 2007-present, Alexandru Mărășteanu +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of this software nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. -------------------------------------------------------------------- +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------- -listr-verbose-renderer 0.5.0 - MIT -https://github.com/SamVerschueren/listr-verbose-renderer#readme -(c) Sam Verschueren (https://github.com/SamVerschueren) -Copyright (c) Sam Verschueren +--------------------------------------------------------- -The MIT License (MIT) +--------------------------------------------------------- -Copyright (c) Sam Verschueren (github.com/SamVerschueren) +sprintf-js 1.0.3 - BSD-3-Clause +https://github.com/alexei/sprintf.js#readme -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2007-2014, Alexandru Marasteanu -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Copyright (c) 2007-2014, Alexandru Marasteanu +All rights reserved. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of this software nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -locate-path 3.0.0 - MIT -https://github.com/sindresorhus/locate-path#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -MIT License +tough-cookie 2.5.0 - BSD-3-Clause +https://github.com/salesforce/tough-cookie -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2015, Salesforce.com, Inc. +Copyright (c) 2018, Salesforce.com, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) 2015, Salesforce.com, Inc. +All rights reserved. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -------------------------------------------------------------------- +3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -------------------------------------------------------------------- +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -lodash 4.17.15 - MIT -https://lodash.com/ -Copyright OpenJS Foundation and other contributors -Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -Copyright OpenJS Foundation and other contributors +--------------------------------------------------------- -Based on Underscore.js, copyright Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors +--------------------------------------------------------- -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/lodash/lodash +fs.realpath 1.0.0 - ISC +https://github.com/isaacs/fs.realpath#readme -The following license applies to all parts of this software except as -documented below: +Copyright (c) Isaac Z. Schlueter and Contributors +Copyright Joyent, Inc. and other Node contributors. -==== +The ISC License -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Copyright (c) Isaac Z. Schlueter and Contributors -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -==== +---- -Copyright and related rights for sample code are waived via CC0. Sample -code is defined as all source code displayed within the prose of the -documentation. +This library bundles a version of the `fs.realpath` and `fs.realpathSync` +methods from Node.js v0.10 under the terms of the Node.js MIT license. -CC0: http://creativecommons.org/publicdomain/zero/1.0/ +Node's license follows, also included at the header of `old.js` which contains +the licensed code: -==== + Copyright Joyent, Inc. and other Node contributors. -Files located in the node_modules and vendor directories are externally -maintained libraries used by this software which have their own -licenses; we recommend you read them, as their terms may differ from the -terms above. + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. -------------------------------------------------------------------- + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -lodash.includes 4.3.0 - MIT -https://lodash.com/ -Copyright jQuery Foundation and other contributors -Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +--------------------------------------------------------- -Copyright jQuery Foundation and other contributors +--------------------------------------------------------- -Based on Underscore.js, copyright Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors +glob 7.1.4 - ISC +https://github.com/isaacs/node-glob#readme -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/lodash/lodash +Copyright (c) Isaac Z. Schlueter and Contributors -The following license applies to all parts of this software except as -documented below: +The ISC License -==== +Copyright (c) Isaac Z. Schlueter and Contributors -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## Glob Logo -==== +Glob's logo created by Tanya Brassie , licensed +under a Creative Commons Attribution-ShareAlike 4.0 International License +https://creativecommons.org/licenses/by-sa/4.0/ -Copyright and related rights for sample code are waived via CC0. Sample -code is defined as all source code displayed within the prose of the -documentation. -CC0: http://creativecommons.org/publicdomain/zero/1.0/ +--------------------------------------------------------- -==== +--------------------------------------------------------- -Files located in the node_modules and vendor directories are externally -maintained libraries used by this software which have their own -licenses; we recommend you read them, as their terms may differ from the -terms above. +har-schema 2.0.0 - ISC +https://github.com/ahmadnassri/har-schema +Copyright (c) 2015, Ahmad Nassri +copyright ahmadnassri.com (https://www.ahmadnassri.com/) -------------------------------------------------------------------- +Copyright (c) 2015, Ahmad Nassri -------------------------------------------------------------------- +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -lodash.isboolean 3.0.3 - MIT -https://lodash.com/ -Copyright 2012-2016 The Dojo Foundation -Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -Copyright 2012-2016 The Dojo Foundation -Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +inflight 1.0.6 - ISC +https://github.com/isaacs/inflight +Copyright (c) Isaac Z. Schlueter -------------------------------------------------------------------- +The ISC License -------------------------------------------------------------------- +Copyright (c) Isaac Z. Schlueter -lodash.isinteger 4.0.4 - MIT -https://lodash.com/ -Copyright jQuery Foundation and other contributors -Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -Copyright jQuery Foundation and other contributors +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -Based on Underscore.js, copyright Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/lodash/lodash +--------------------------------------------------------- -The following license applies to all parts of this software except as -documented below: +--------------------------------------------------------- -==== +inherits 2.0.3 - ISC +https://github.com/isaacs/inherits#readme -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Copyright (c) Isaac Z. Schlueter -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The ISC License -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Copyright (c) Isaac Z. Schlueter -==== +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -Copyright and related rights for sample code are waived via CC0. Sample -code is defined as all source code displayed within the prose of the -documentation. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. -CC0: http://creativecommons.org/publicdomain/zero/1.0/ -==== -Files located in the node_modules and vendor directories are externally -maintained libraries used by this software which have their own -licenses; we recommend you read them, as their terms may differ from the -terms above. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +json-stringify-safe 5.0.1 - ISC +https://github.com/isaacs/json-stringify-safe -------------------------------------------------------------------- +Copyright (c) Isaac Z. Schlueter and Contributors -lodash.isnumber 3.0.3 - MIT -https://lodash.com/ -Copyright 2012-2016 The Dojo Foundation -Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +The ISC License -Copyright 2012-2016 The Dojo Foundation -Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors +Copyright (c) Isaac Z. Schlueter and Contributors -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +lru-cache 4.1.5 - ISC +https://github.com/isaacs/node-lru-cache#readme -lodash.isplainobject 4.0.6 - MIT -https://lodash.com/ -Copyright jQuery Foundation and other contributors -Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +Copyright (c) Isaac Z. Schlueter and Contributors -Copyright jQuery Foundation and other contributors +The ISC License -Based on Underscore.js, copyright Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors +Copyright (c) Isaac Z. Schlueter and Contributors -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/lodash/lodash +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -The following license applies to all parts of this software except as -documented below: +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -==== -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +lru-cache 5.1.1 - ISC +https://github.com/isaacs/node-lru-cache#readme -==== +Copyright (c) Isaac Z. Schlueter and Contributors -Copyright and related rights for sample code are waived via CC0. Sample -code is defined as all source code displayed within the prose of the -documentation. +The ISC License -CC0: http://creativecommons.org/publicdomain/zero/1.0/ +Copyright (c) Isaac Z. Schlueter and Contributors -==== +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -Files located in the node_modules and vendor directories are externally -maintained libraries used by this software which have their own -licenses; we recommend you read them, as their terms may differ from the -terms above. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -lodash.isstring 4.0.1 - MIT -https://lodash.com/ -Copyright 2012-2016 The Dojo Foundation -Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +minimatch 3.0.4 - ISC +https://github.com/isaacs/minimatch#readme -Copyright 2012-2016 The Dojo Foundation -Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors +Copyright (c) Isaac Z. Schlueter and Contributors -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +The ISC License -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Copyright (c) Isaac Z. Schlueter and Contributors -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -lodash.once 4.1.1 - MIT -https://lodash.com/ -Copyright jQuery Foundation and other contributors -Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +--------------------------------------------------------- -Copyright jQuery Foundation and other contributors +once 1.4.0 - ISC +https://github.com/isaacs/once#readme -Based on Underscore.js, copyright Jeremy Ashkenas, -DocumentCloud and Investigative Reporters & Editors +Copyright (c) Isaac Z. Schlueter and Contributors -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/lodash/lodash +The ISC License -The following license applies to all parts of this software except as -documented below: +Copyright (c) Isaac Z. Schlueter and Contributors -==== +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -==== +--------------------------------------------------------- -Copyright and related rights for sample code are waived via CC0. Sample -code is defined as all source code displayed within the prose of the -documentation. +pseudomap 1.0.2 - ISC +https://github.com/isaacs/pseudomap#readme -CC0: http://creativecommons.org/publicdomain/zero/1.0/ +Copyright (c) Isaac Z. Schlueter and Contributors -==== +The ISC License -Files located in the node_modules and vendor directories are externally -maintained libraries used by this software which have their own -licenses; we recommend you read them, as their terms may differ from the -terms above. +Copyright (c) Isaac Z. Schlueter and Contributors +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- -log-symbols 2.2.0 - MIT -https://github.com/sindresorhus/log-symbols#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -MIT License +--------------------------------------------------------- -Copyright (c) Sindre Sorhus (sindresorhus.com) +rimraf 2.7.1 - ISC +https://github.com/isaacs/rimraf#readme -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) Isaac Z. Schlueter and Contributors -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The ISC License -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Copyright (c) Isaac Z. Schlueter and Contributors +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- -log-symbols 1.0.2 - MIT -https://github.com/sindresorhus/log-symbols -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -The MIT License (MIT) +--------------------------------------------------------- -Copyright (c) Sindre Sorhus (sindresorhus.com) +sax 1.2.4 - ISC +https://github.com/isaacs/sax-js#readme -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) Isaac Z. Schlueter and Contributors +Copyright Mathias Bynens -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The ISC License -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Copyright (c) Isaac Z. Schlueter and Contributors +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- +==== -log-update 2.3.0 - MIT -https://github.com/sindresorhus/log-update#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +`String.fromCodePoint` by Mathias Bynens used according to terms of MIT +License, as follows: -MIT License + Copyright Mathias Bynens -Copyright (c) Sindre Sorhus (sindresorhus.com) + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +semver 5.7.1 - ISC +https://github.com/npm/node-semver#readme -logform 2.1.2 - MIT -https://github.com/winstonjs/logform#readme -Copyright (c) 2017 Charlie Robbins & the Contributors. +Copyright Isaac Z. +Copyright Isaac Z. Schlueter +Copyright (c) Isaac Z. Schlueter and Contributors -MIT License +The ISC License -Copyright (c) 2017 Charlie Robbins & the Contributors. +Copyright (c) Isaac Z. Schlueter and Contributors -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +semver 7.3.2 - ISC +https://github.com/npm/node-semver#readme -lokijs 1.5.7 - MIT -http://lokijs.org -Copyright (c) 2015 TechFort +Copyright Isaac Z. Schlueter +Copyright (c) Isaac Z. Schlueter and Contributors -Copyright (c) 2015 TechFort +The ISC License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) Isaac Z. Schlueter and Contributors -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -loose-envify 1.4.0 - MIT -https://github.com/zertosh/loose-envify -Copyright (c) 2015 Andres Suarez +setprototypeof 1.1.1 - ISC +https://github.com/wesleytodd/setprototypeof -The MIT License (MIT) +Copyright (c) 2015, Wes Todd -Copyright (c) 2015 Andres Suarez +Copyright (c) 2015, Wes Todd -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +wrappy 1.0.2 - ISC +https://github.com/npm/wrappy -map-cache 0.2.2 - MIT -https://github.com/jonschlinkert/map-cache -Copyright (c) 2015, Jon Schlinkert. -Copyright (c) 2015-2016, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). +Copyright (c) Isaac Z. Schlueter and Contributors -The MIT License (MIT) +The ISC License -Copyright (c) 2015-2016, Jon Schlinkert. +Copyright (c) Isaac Z. Schlueter and Contributors -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +yallist 2.1.2 - ISC +https://github.com/isaacs/yallist#readme -map-visit 1.0.0 - MIT -https://github.com/jonschlinkert/map-visit -Copyright (c) 2015-2017, Jon Schlinkert -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). +Copyright (c) Isaac Z. Schlueter and Contributors -The MIT License (MIT) +The ISC License -Copyright (c) 2015-2017, Jon Schlinkert +Copyright (c) Isaac Z. Schlueter and Contributors -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +yallist 3.1.1 - ISC +https://github.com/isaacs/yallist#readme -markdown-it 8.4.2 - MIT -https://github.com/markdown-it/markdown-it#readme -(c) (tm) -Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. -Copyright Joyent, Inc. and other Node contributors. +Copyright (c) Isaac Z. Schlueter and Contributors -Copyright (c) 2014 Vitaly Puzrin, Alex Kocharin. +The ISC License -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +Copyright (c) Isaac Z. Schlueter and Contributors -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -matcher 1.1.1 - MIT -https://github.com/sindresorhus/matcher#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +xmldom 0.3.0 - LGPL-2.0 OR MIT OR (LGPL-2.0 AND MIT) +https://github.com/xmldom/xmldom -MIT License -Copyright (c) Sindre Sorhus (sindresorhus.com) +You can choose any one of these licenses: -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +- MIT: https://opensource.org/licenses/MIT +- LGPL: http://www.gnu.org/licenses/lgpl.html -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +@azure/ms-rest-azure-env 1.1.2 - MIT +https://github.com/Azure/ms-rest-azure-env -------------------------------------------------------------------- +Copyright (c) Microsoft Corporation. -mdurl 1.0.1 - MIT -https://github.com/markdown-it/mdurl#readme -Copyright (c) 2015 Vitaly Puzrin, Alex Kocharin. -Copyright Joyent, Inc. and other Node contributors. + MIT License -Copyright (c) 2015 Vitaly Puzrin, Alex Kocharin. + Copyright (c) Microsoft Corporation. All rights reserved. -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE --------------------------------------------------------------------------------- -.parse() is based on Joyent's node.js `url` code: +--------------------------------------------------------- -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +@azure/ms-rest-js 1.8.13 - MIT +https://github.com/Azure/ms-rest-js -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. +Copyright (c) Microsoft Corporation. +Copyright (c) 2010-2016 Robert Kieffer and other contributors + MIT License -------------------------------------------------------------------- + Copyright (c) Microsoft Corporation. All rights reserved. -------------------------------------------------------------------- + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -media-typer 0.3.0 - MIT -https://github.com/jshttp/media-typer -Copyright (c) 2014 Douglas Christopher Wilson + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. -(The MIT License) + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE -Copyright (c) 2014 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +@azure/ms-rest-nodeauth 2.0.2 - MIT +https://github.com/Azure/ms-rest-nodeauth +Copyright (c) Microsoft Corporation. -------------------------------------------------------------------- + MIT License -------------------------------------------------------------------- + Copyright (c) Microsoft Corporation. All rights reserved. -merge-descriptors 1.0.1 - MIT -https://github.com/component/merge-descriptors -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2015 Douglas Christopher Wilson -Copyright (c) 2013 Jonathan Ong -Copyright (c) 2015 Douglas Christopher Wilson + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -(The MIT License) + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. -Copyright (c) 2013 Jonathan Ong -Copyright (c) 2015 Douglas Christopher Wilson + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +@types/node 12.7.5 - MIT -------------------------------------------------------------------- -------------------------------------------------------------------- +Copyright (c) Microsoft Corporation. -methods 1.1.2 - MIT -https://github.com/jshttp/methods -Copyright (c) 2013-2014 TJ Holowaychuk -Copyright (c) 2015-2016 Douglas Christopher Wilson -Copyright (c) 2013-2014 TJ Holowaychuk -Copyright (c) 2015-2016 Douglas Christopher Wilson +MIT License -(The MIT License) +Copyright (c) -Copyright (c) 2013-2014 TJ Holowaychuk -Copyright (c) 2015-2016 Douglas Christopher Wilson +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- +@types/node 8.10.63 - MIT -------------------------------------------------------------------- -------------------------------------------------------------------- -micromatch 3.1.10 - MIT -https://github.com/micromatch/micromatch -Copyright (c) 2014-2018, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). +MIT License -The MIT License (MIT) +Copyright (c) -Copyright (c) 2014-2018, Jon Schlinkert. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +@types/node 14.14.24 - MIT -------------------------------------------------------------------- -mime 1.6.0 - MIT -https://github.com/broofa/node-mime#readme -Copyright (c) 2010 Benjamin Thomas, Robert Kieffer +Copyright (c) Microsoft Corporation. -The MIT License (MIT) +MIT License -Copyright (c) 2010 Benjamin Thomas, Robert Kieffer +Copyright (c) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +@types/tunnel 0.0.0 - MIT -mime-db 1.40.0 - MIT -https://github.com/jshttp/mime-db#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014 Jonathan Ong me@jongleberry.com +Copyright (c) Microsoft Corporation. -The MIT License (MIT) +MIT License -Copyright (c) 2014 Jonathan Ong me@jongleberry.com +Copyright (c) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +accepts 1.3.7 - MIT +https://github.com/jshttp/accepts#readme -mime-types 2.1.24 - MIT -https://github.com/jshttp/mime-types#readme Copyright (c) 2014 Jonathan Ong Copyright (c) 2015 Douglas Christopher Wilson Copyright (c) 2014 Jonathan Ong @@ -15799,123 +2454,105 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -mimic-fn 1.2.0 - MIT -https://github.com/sindresorhus/mimic-fn#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License +--------------------------------------------------------- -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +ajv 6.12.5 - MIT +https://github.com/ajv-validator/ajv -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +(c) 2011 Gary Court. +Copyright 2011 Gary Court. +Copyright (c) 2015-2017 Evgeny Poberezkin -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The MIT License (MIT) +Copyright (c) 2015-2017 Evgeny Poberezkin -------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -------------------------------------------------------------------- +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -minimist 0.0.8 - MIT -https://github.com/substack/minimist +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -This software is released under the MIT license: -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +ansicolors 0.3.2 - MIT -------------------------------------------------------------------- -------------------------------------------------------------------- +Copyright 2013 Thorsten Lorenz. -minimist 1.2.5 - MIT -https://github.com/substack/minimist +Copyright 2013 Thorsten Lorenz. +All rights reserved. -This software is released under the MIT license: +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +ansi-styles 3.2.1 - MIT +https://github.com/chalk/ansi-styles#readme -mixin-deep 1.3.2 - MIT -https://github.com/jonschlinkert/mixin-deep -Copyright (c) 2014-2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). +Copyright (c) Sindre Sorhus (sindresorhus.com) -The MIT License (MIT) +MIT License -Copyright (c) 2014-2015, 2017, Jon Schlinkert. +Copyright (c) Sindre Sorhus (sindresorhus.com) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -mkdirp 0.5.1 - MIT -https://github.com/substack/node-mkdirp#readme -Copyright 2010 James Halliday (mail@substack.net) +any-promise 1.3.0 - MIT +http://github.com/kevinbeaty/any-promise -Copyright 2010 James Halliday (mail@substack.net) +Copyright (c) 2014-2016 Kevin Beaty -This project is free software released under the MIT/X11 license: +Copyright (C) 2014-2016 Kevin Beaty Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -15936,17 +2573,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -mkdirp 0.5.5 - MIT -https://github.com/substack/node-mkdirp#readme -Copyright 2010 James Halliday (mail@substack.net) +args 5.0.1 - MIT +https://github.com/leo/args#readme + +Copyright (c) 2016 Leonard Lamprecht -Copyright 2010 James Halliday (mail@substack.net) +The MIT License (MIT) -This project is free software released under the MIT/X11 license: +Copyright (c) 2016 Leonard Lamprecht Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -15955,164 +2593,112 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -mocha 5.2.0 - MIT -https://mochajs.org -Copyright (c) 2011-2018 JS Foundation -Copyright Joyent, Inc. and other Node contributors. -Copyright (c) 2011 TJ Holowaychuk -Copyright (c) 2009-2015, Kevin Decker - -(The MIT License) - -Copyright (c) 2011-2018 JS Foundation and contributors, https://js.foundation - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +array-flatten 1.1.1 - MIT +https://github.com/blakeembrey/array-flatten -------------------------------------------------------------------- +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) -moment 2.24.0 - MIT -http://momentjs.com -Copyright (c) JS Foundation and other contributors +The MIT License (MIT) -Copyright (c) JS Foundation and other contributors +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -moment-timezone 0.5.26 - MIT -http://momentjs.com/timezone/ -Copyright (c) JS Foundation and other contributors +asn1 0.2.4 - MIT +https://github.com/joyent/node-asn1#readme -The MIT License (MIT) +Copyright (c) 2011 Mark Cavage +Copyright 2011 Mark Cavage -Copyright (c) JS Foundation and other contributors +Copyright (c) 2011 Mark Cavage, All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -morgan 1.9.1 - MIT -https://github.com/expressjs/morgan#readme -Copyright (c) 2010 Sencha Inc. -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2011 TJ Holowaychuk -Copyright (c) 2014-2017 Douglas Christopher Wilson -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2017 Douglas Christopher Wilson +--------------------------------------------------------- -(The MIT License) +assert-plus 1.0.0 - MIT +https://github.com/mcavage/node-assert-plus#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2017 Douglas Christopher Wilson +Copyright 2015 Joyent, Inc. +Copyright (c) 2012 Mark Cavage +Copyright (c) 2012, Mark Cavage. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +MIT License -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Copyright (c) -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -mri 1.1.4 - MIT -https://github.com/lukeed/mri#readme -(c) Luke Edwards (https://lukeed.com) -Copyright (c) Luke Edwards (lukeed.com) +--------------------------------------------------------- -The MIT License (MIT) +async 2.6.3 - MIT +https://caolan.github.io/async/ -Copyright (c) Luke Edwards (lukeed.com) +Copyright (c) 2010-2018 Caolan McMahon + +Copyright (c) 2010-2018 Caolan McMahon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16133,17 +2719,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -ms 2.1.1 - MIT -https://github.com/zeit/ms#readme -Copyright (c) 2016 Zeit, Inc. +asynckit 0.4.0 - MIT +https://github.com/alexindigo/asynckit#readme + +Copyright (c) 2016 Alex Indigo The MIT License (MIT) -Copyright (c) 2016 Zeit, Inc. +Copyright (c) 2016 Alex Indigo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16164,24 +2751,23 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -ms 2.1.2 - MIT -https://github.com/zeit/ms#readme -Copyright (c) 2016 Zeit, Inc. +aws4 1.10.1 - MIT +https://github.com/mhart/aws4#readme -The MIT License (MIT) +Copyright 2013 Michael Hart (michael.hart.au@gmail.com) -Copyright (c) 2016 Zeit, Inc. +Copyright 2013 Michael Hart (michael.hart.au@gmail.com) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. @@ -16195,17 +2781,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -ms 2.0.0 - MIT -https://github.com/zeit/ms#readme -Copyright (c) 2016 Zeit, Inc. +axios 0.19.0 - MIT +https://github.com/axios/axios -The MIT License (MIT) +(c) 2019 by Matt Zabriskie +Copyright (c) 2014-present Matt Zabriskie -Copyright (c) 2016 Zeit, Inc. +Copyright (c) 2014-present Matt Zabriskie Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16214,152 +2800,162 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -multistream 2.1.1 - MIT -https://github.com/feross/multistream -Copyright (c) Feross Aboukhadijeh -Copyright (c) Feross Aboukhadijeh (http://feross.org). +balanced-match 1.0.0 - MIT +https://github.com/juliangruber/balanced-match -The MIT License (MIT) +Copyright (c) 2013 Julian Gruber -Copyright (c) Feross Aboukhadijeh +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -mysql2 2.1.0 - MIT -https://github.com/sidorares/node-mysql2#readme -Copyright (c) 2016 Andrey Sidorov (sidorares@yandex.ru) and contributors +basic-auth 2.0.1 - MIT +https://github.com/jshttp/basic-auth#readme -Copyright (c) 2016 Andrey Sidorov (sidorares@yandex.ru) and contributors +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2013 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015-2016 Douglas Christopher Wilson - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: +(The MIT License) - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. +Copyright (c) 2013 TJ Holowaychuk +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015-2016 Douglas Christopher Wilson - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -named-placeholders 1.1.2 - MIT -https://github.com/sidorares/named-placeholders#readme -Copyright (c) 2014 Andrey Sidorov +bl 3.0.1 - MIT +https://github.com/rvagg/bl + +Copyright (c) 2013-2018 bl contributors The MIT License (MIT) +===================== -Copyright (c) 2014 Andrey Sidorov +Copyright (c) 2013-2018 bl contributors +---------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +*bl contributors listed at * -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -nanomatch 1.2.13 - MIT -https://github.com/micromatch/nanomatch -Copyright (c) 2016-2018, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). +body-parser 1.19.0 - MIT +https://github.com/expressjs/body-parser#readme -The MIT License (MIT) +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) 2016-2018, Jon Schlinkert. +(The MIT License) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -native-duplexpair 1.0.0 - MIT -https://github.com/tediousjs/native-duplexpair#readme -Copyright (c) 2017 Anna Henningsen +--------------------------------------------------------- -The MIT License (MIT) +brace-expansion 1.1.11 - MIT +https://github.com/juliangruber/brace-expansion -Copyright (c) 2017 Anna Henningsen +Copyright (c) 2013 Julian Gruber + +MIT License + +Copyright (c) 2013 Julian Gruber Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16380,26 +2976,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +bytes 3.1.0 - MIT +https://github.com/visionmedia/bytes.js#readme -negotiator 0.6.2 - MIT -https://github.com/jshttp/negotiator#readme -Copyright (c) 2012 Federico Romero -Copyright (c) 2014 Federico Romero -Copyright (c) 2012 Isaac Z. Schlueter -Copyright (c) 2012-2014 Federico Romero -Copyright (c) 2012-2014 Isaac Z. Schlueter -Copyright (c) 2015 Douglas Christopher Wilson -Copyright (c) 2014-2015 Douglas Christopher Wilson +Copyright (c) 2015 Jed Watson +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015 Jed Watson +Copyright (c) 2012-2014 TJ Holowaychuk (The MIT License) -Copyright (c) 2012-2014 Federico Romero -Copyright (c) 2012-2014 Isaac Z. Schlueter -Copyright (c) 2014-2015 Douglas Christopher Wilson +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015 Jed Watson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -16421,208 +3013,176 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -nice-try 1.0.5 - MIT -https://github.com/electerious/nice-try -Copyright (c) 2018 Tobias Reich +camelcase 5.0.0 - MIT +https://github.com/sindresorhus/camelcase#readme -The MIT License (MIT) +(c) Sindre Sorhus (https://sindresorhus.com) +Copyright (c) Sindre Sorhus (sindresorhus.com) -Copyright (c) 2018 Tobias Reich +MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) Sindre Sorhus (sindresorhus.com) -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -node-fetch 2.6.0 - MIT -https://github.com/bitinn/node-fetch -Copyright (c) 2016 David Frank +--------------------------------------------------------- -The MIT License (MIT) +cardinal 2.1.1 - MIT +https://github.com/thlorenz/cardinal#readme -Copyright (c) 2016 David Frank +Copyright 2012 Thorsten Lorenz. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright 2012 Thorsten Lorenz. +All rights reserved. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -npm-path 2.0.4 - MIT -https://github.com/timoxley/npm-path -Copyright (c) 2014 Tim Oxley +chalk 2.4.2 - MIT +https://github.com/chalk/chalk#readme -The MIT License (MIT) +Copyright (c) Sindre Sorhus (sindresorhus.com) -Copyright (c) 2014 Tim Oxley +MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) Sindre Sorhus (sindresorhus.com) -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -npm-run-path 2.0.2 - MIT -https://github.com/sindresorhus/npm-run-path#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -The MIT License (MIT) +color 3.0.0 - MIT +https://github.com/Qix-/color#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2012 Heather Arthur -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2012 Heather Arthur -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- -npm-which 3.0.1 - MIT -https://github.com/timoxley/npm-which -Copyright (c) 2014 Tim Oxley +--------------------------------------------------------- -The MIT License (MIT) +--------------------------------------------------------- -Copyright (c) 2014 Tim Oxley +color-convert 1.9.3 - MIT +https://github.com/Qix-/color-convert#readme -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2011-2016, Heather Arthur and Josh Junon. +Copyright (c) 2011-2016 Heather Arthur -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Copyright (c) 2011-2016 Heather Arthur -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -number-is-nan 1.0.1 - MIT -https://github.com/sindresorhus/number-is-nan#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) -The MIT License (MIT) +--------------------------------------------------------- -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +color-name 1.1.3 - MIT +https://github.com/dfcreative/color-name + +Copyright (c) 2015 Dmitry Ivanov + +The MIT License (MIT) +Copyright (c) 2015 Dmitry Ivanov + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +colornames 1.1.1 - MIT +https://github.com/timoxley/colornames#readme -object-assign 4.1.1 - MIT -https://github.com/sindresorhus/object-assign#readme -(c) Sindre Sorhus -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2015 Tim Oxley The MIT License (MIT) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2015 Tim Oxley Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16643,17 +3203,23 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -object-copy 0.1.0 - MIT -https://github.com/jonschlinkert/object-copy -Copyright (c) 2016, Jon Schlinkert. +colors 1.3.3 - MIT +https://github.com/Marak/colors.js -The MIT License (MIT) +Copyright (c) Marak Squires +Copyright (c) Sindre Sorhus (sindresorhus.com) -Copyright (c) 2016, Jon Schlinkert. +MIT License + +Original Library + - Copyright (c) Marak Squires + +Additional Functionality + - Copyright (c) Sindre Sorhus (sindresorhus.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16674,14 +3240,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- -------------------------------------------------------------------- +colorspace 1.1.2 - MIT +https://github.com/3rd-Eden/colorspace -object-inspect 1.6.0 - MIT -https://github.com/substack/object-inspect +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman -This software is released under the MIT license: +The MIT License (MIT) + +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -16701,48 +3271,48 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -object-keys 1.1.1 - MIT -https://github.com/ljharb/object-keys#readme -Copyright (c) 2013 Jordan Harband +color-string 1.5.3 - MIT +https://github.com/Qix-/color-string#readme -The MIT License (MIT) +Copyright (c) 2011 Heather Arthur -Copyright (C) 2013 Jordan Harband +Copyright (c) 2011 Heather Arthur -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- -object-visit 1.0.1 - MIT -https://github.com/jonschlinkert/object-visit -Copyright (c) 2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). +--------------------------------------------------------- -The MIT License (MIT) +--------------------------------------------------------- + +combined-stream 1.0.8 - MIT +https://github.com/felixge/node-combined-stream + +Copyright (c) 2011 Debuggable Limited -Copyright (c) 2015, 2017, Jon Schlinkert +Copyright (c) 2011 Debuggable Limited Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16763,86 +3333,79 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -object.getownpropertydescriptors 2.0.3 - MIT -https://github.com/ljharb/object.getownpropertydescriptors#readme -Copyright (c) 2015 Jordan Harband +concat-map 0.0.1 - MIT +https://github.com/substack/node-concat-map -The MIT License (MIT) -Copyright (c) 2015 Jordan Harband +This software is released under the MIT license: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +content-disposition 0.5.3 - MIT +https://github.com/jshttp/content-disposition#readme -object.pick 1.3.0 - MIT -https://github.com/jonschlinkert/object.pick -Copyright (c) 2014-2016, Jon Schlinkert. -Copyright (c) 2014-2015 Jon Schlinkert, contributors. -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). +Copyright (c) 2014-2017 Douglas Christopher Wilson -The MIT License (MIT) +(The MIT License) -Copyright (c) 2014-2016, Jon Schlinkert. +Copyright (c) 2014-2017 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -on-finished 2.3.0 - MIT -https://github.com/jshttp/on-finished -Copyright (c) 2013 Jonathan Ong -Copyright (c) 2014 Douglas Christopher Wilson -Copyright (c) 2013 Jonathan Ong -Copyright (c) 2014 Douglas Christopher Wilson +content-type 1.0.4 - MIT +https://github.com/jshttp/content-type#readme + +Copyright (c) 2015 Douglas Christopher Wilson (The MIT License) -Copyright (c) 2013 Jonathan Ong -Copyright (c) 2014 Douglas Christopher Wilson +Copyright (c) 2015 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -16864,17 +3427,22 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -on-headers 1.0.2 - MIT -https://github.com/jshttp/on-headers#readme -Copyright (c) 2014 Douglas Christopher Wilson +cookie 0.4.0 - MIT +https://github.com/jshttp/cookie#readme + +Copyright (c) 2012-2014 Roman Shtylman +Copyright (c) 2015 Douglas Christopher Wilson +Copyright (c) 2012-2014 Roman Shtylman +Copyright (c) 2015 Douglas Christopher Wilson (The MIT License) -Copyright (c) 2014 Douglas Christopher Wilson +Copyright (c) 2012-2014 Roman Shtylman +Copyright (c) 2015 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -16896,56 +3464,42 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -one-time 0.0.4 - MIT -https://github.com/unshiftio/one-time -Copyright (c) 2015 Unshift.io, Arnout Kazemier +--------------------------------------------------------- -The MIT License (MIT) +cookie-signature 1.0.6 - MIT +https://github.com/visionmedia/node-cookie-signature -Copyright (c) 2015 Unshift.io, Arnout Kazemier, the Contributors. +Copyright (c) 2012 LearnBoost -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +MIT License -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Copyright (c) -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -onetime 2.0.1 - MIT -https://github.com/sindresorhus/onetime#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +core-util-is 1.0.2 - MIT +https://github.com/isaacs/core-util-is#readme -The MIT License (MIT) +Copyright Joyent, Inc. and other Node contributors. -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright Node.js contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -16955,87 +3509,62 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -os 0.1.1 - MIT -https://github.com/DiegoRBaquero/node-os#readme -Copyright (c) 2016 Diego Rodriguez Baquero -Copyright (c) Diego Rodriguez Baquero (https://diegorbaquero.com). - -The MIT License (MIT) - -Copyright (c) 2016 Diego Rodríguez Baquero - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +dashdash 1.14.1 - MIT +https://github.com/trentm/node-dashdash#readme -------------------------------------------------------------------- +Copyright 2016 Trent Mick +Copyright 2016 Joyent, Inc. +Copyright (c) 2013 Joyent Inc. +Copyright (c) 2013 Trent Mick. -os-homedir 1.0.2 - MIT -https://github.com/sindresorhus/os-homedir#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +# This is the MIT license -The MIT License (MIT) +Copyright (c) 2013 Trent Mick. All rights reserved. +Copyright (c) 2013 Joyent Inc. All rights reserved. -Copyright (c) Sindre Sorhus (sindresorhus.com) +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -os-tmpdir 1.0.2 - MIT -https://github.com/sindresorhus/os-tmpdir#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +date-utils 1.2.21 - MIT +https://jerrysievert.github.io/date-utils/ -The MIT License (MIT) +(c) 2011 by Jerry Sievert +Copyright 2012 Twitter, Inc. +Copyright 2013 Twitter, Inc. +(c) 2005, 2013 jQuery Foundation, Inc. -Copyright (c) Sindre Sorhus (sindresorhus.com) +© 2011 by Jerry Sievert Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17056,198 +3585,313 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -p-finally 1.0.0 - MIT -https://github.com/sindresorhus/p-finally#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -The MIT License (MIT) + 1. Definitions. -Copyright (c) Sindre Sorhus (sindresorhus.com) + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. -------------------------------------------------------------------- + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. -------------------------------------------------------------------- + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). -p-limit 2.2.1 - MIT -https://github.com/sindresorhus/p-limit#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. -MIT License + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." -Copyright (c) Sindre Sorhus (sindresorhus.com) + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and -------------------------------------------------------------------- + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and -------------------------------------------------------------------- + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and -p-locate 3.0.0 - MIT -https://github.com/sindresorhus/p-locate#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. -MIT License + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. -Copyright (c) Sindre Sorhus (sindresorhus.com) + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. -------------------------------------------------------------------- + END OF TERMS AND CONDITIONS -------------------------------------------------------------------- + APPENDIX: How to apply the Apache License to your work. -p-map 1.2.0 - MIT -https://github.com/sindresorhus/p-map#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. -MIT License + Copyright [yyyy] [name of copyright owner] -Copyright (c) Sindre Sorhus (sindresorhus.com) + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + http://www.apache.org/licenses/LICENSE-2.0 -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +debug 3.1.0 - MIT +https://github.com/visionmedia/debug#readme -p-map 2.1.0 - MIT -https://github.com/sindresorhus/p-map#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2014 TJ Holowaychuk +Copyright (c) 2014-2017 TJ Holowaychuk -MIT License +(The MIT License) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2014 TJ Holowaychuk -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the 'Software'), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -p-try 2.2.0 - MIT -https://github.com/sindresorhus/p-try#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -MIT License +debug 4.1.1 - MIT +https://github.com/visionmedia/debug#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2014 TJ Holowaychuk +Copyright (c) 2014-2017 TJ Holowaychuk -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +(The MIT License) -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Copyright (c) 2014 TJ Holowaychuk -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the 'Software'), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -parse-json 4.0.0 - MIT -https://github.com/sindresorhus/parse-json#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) -MIT License +--------------------------------------------------------- -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +debug 2.6.9 - MIT +https://github.com/visionmedia/debug#readme -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Copyright (c) 2014 TJ Holowaychuk +Copyright (c) 2014-2016 TJ Holowaychuk -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +(The MIT License) +Copyright (c) 2014 TJ Holowaychuk -------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software +and associated documentation files (the 'Software'), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -------------------------------------------------------------------- +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. -parse-semver 1.1.1 - MIT -https://github.com/tunnckocore/parse-semver#readme -Copyright (c) 2015 Charlike Mike Reagent, contributors. -Copyright (c) 2015-2016 Charlike Make Reagent (http://j.mp/1stW47C) -Copyright (c) 2015-2016 Charlike Mike Reagent <@tunnckoCore> (http://www.tunnckocore.tk) +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# The MIT License -Copyright (c) 2015-2016 [Charlike Make Reagent](http://j.mp/1stW47C) -> Permission is hereby granted, free of charge, to any person obtaining a copy -> of this software and associated documentation files (the "Software"), to deal -> in the Software without restriction, including without limitation the rights -> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -> copies of the Software, and to permit persons to whom the Software is -> furnished to do so, subject to the following conditions: -> -> The above copyright notice and this permission notice shall be included in -> all copies or substantial portions of the Software. -> -> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -> SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +delayed-stream 1.0.0 - MIT +https://github.com/felixge/node-delayed-stream -parse5 3.0.3 - MIT -https://github.com/inikulin/parse5 -Copyright (c) 2013-2016 Ivan Nikulin (ifaaan@gmail.com, https://github.com/inikulin) +Copyright (c) 2011 Debuggable Limited -Copyright (c) 2013-2016 Ivan Nikulin (ifaaan@gmail.com, https://github.com/inikulin) +Copyright (c) 2011 Debuggable Limited Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17268,22 +3912,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -parseurl 1.3.3 - MIT -https://github.com/pillarjs/parseurl#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2017 Douglas Christopher Wilson -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2017 Douglas Christopher Wilson +depd 1.1.2 - MIT +https://github.com/dougwilson/nodejs-depd#readme +Copyright (c) 2014 Douglas Christopher Wilson +Copyright (c) 2015 Douglas Christopher Wilson +Copyright (c) 2014-2015 Douglas Christopher Wilson +Copyright (c) 2014-2017 Douglas Christopher Wilson (The MIT License) -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2017 Douglas Christopher Wilson +Copyright (c) 2014-2017 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -17305,50 +3948,54 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +depd 2.0.0 - MIT +https://github.com/dougwilson/nodejs-depd#readme -pascalcase 0.1.1 - MIT -https://github.com/jonschlinkert/pascalcase -Copyright (c) 2015 Jon Schlinkert -Copyright (c) 2015, Jon Schlinkert. +Copyright (c) 2015 Douglas Christopher Wilson +Copyright (c) 2014-2018 Douglas Christopher Wilson -The MIT License (MIT) +(The MIT License) -Copyright (c) 2015, Jon Schlinkert. +Copyright (c) 2014-2018 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +destroy 1.0.4 - MIT +https://github.com/stream-utils/destroy + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014 Jonathan Ong me@jongleberry.com -path-exists 3.0.0 - MIT -https://github.com/sindresorhus/path-exists#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) The MIT License (MIT) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2014 Jonathan Ong me@jongleberry.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17369,50 +4016,49 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -path-is-absolute 1.0.1 - MIT -https://github.com/sindresorhus/path-is-absolute#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +diagnostics 1.1.1 - MIT +https://github.com/bigpipe/diagnostics + +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman The MIT License (MIT) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -path-key 2.0.1 - MIT -https://github.com/sindresorhus/path-key#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +dottie 2.0.2 - MIT +https://github.com/mickhansen/dottie.js#readme -The MIT License (MIT) +Copyright (c) 2013-2014 Mick Hansen. http://mhansen.io -Copyright (c) Sindre Sorhus (sindresorhus.com) +The MIT License + +Copyright (c) 2013-2014 Mick Hansen. http://mhansen.io Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17433,38 +4079,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -path-key 3.1.0 - MIT -https://github.com/sindresorhus/path-key#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +ecc-jsbn 0.1.2 - MIT +https://github.com/quartzjer/ecc-jsbn -path-parse 1.0.6 - MIT -https://github.com/jbgutierrez/path-parse#readme -Copyright (c) 2015 Javier Blanco -(c) Javier Blanco (http://jbgutierrez.info) +Copyright (c) 2003-2005 Tom Wu +Copyright (c) 2014 Jeremie Miller The MIT License (MIT) -Copyright (c) 2015 Javier Blanco +Copyright (c) 2014 Jeremie Miller Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17484,18 +4113,20 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +ee-first 1.1.1 - MIT +https://github.com/jonathanong/ee-first + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014 Jonathan Ong me@jongleberry.com -path-to-regexp 0.1.7 - MIT -https://github.com/component/path-to-regexp#readme -Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) The MIT License (MIT) -Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) +Copyright (c) 2014 Jonathan Ong me@jongleberry.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17516,48 +4147,80 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- -------------------------------------------------------------------- +enabled 1.0.2 - MIT +https://github.com/bigpipe/enabled#readme -pend 1.2.0 - MIT -Copyright (c) 2014 Andrew Kelley +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman -The MIT License (Expat) +The MIT License (MIT) -Copyright (c) 2014 Andrew Kelley +Copyright (c) 2015 Arnout Kazemier, Martijn Swaagman, the Contributors. -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation files -(the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +encodeurl 1.0.2 - MIT +https://github.com/pillarjs/encodeurl#readme + +Copyright (c) 2016 Douglas Christopher Wilson + +(The MIT License) + +Copyright (c) 2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -performance-now 2.1.0 - MIT -https://github.com/braveg1rl/performance-now -Copyright (c) 2013 Braveg1rl -Copyright (c) 2017 Braveg1rl +env-variable 0.0.5 - MIT +https://github.com/3rd-Eden/env-variable -Copyright (c) 2013 Braveg1rl +Copyright 2014 Arnout Kazemier + +Copyright 2014 Arnout Kazemier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: @@ -17565,32 +4228,51 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -pify 3.0.0 - MIT -https://github.com/sindresorhus/pify#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -MIT License +escape-html 1.0.3 - MIT +https://github.com/component/escape-html -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2015 Andreas Lubbe +Copyright (c) 2012-2013 TJ Holowaychuk +Copyright (c) 2015 Tiancheng Timothy Gu -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +(The MIT License) -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Copyright (c) 2012-2013 TJ Holowaychuk +Copyright (c) 2015 Andreas Lubbe +Copyright (c) 2015 Tiancheng "Timothy" Gu -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +escape-string-regexp 1.0.5 - MIT +https://github.com/sindresorhus/escape-string-regexp -pify 2.3.0 - MIT -https://github.com/sindresorhus/pify (c) Sindre Sorhus (http://sindresorhus.com) Copyright (c) Sindre Sorhus (sindresorhus.com) @@ -17617,100 +4299,123 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -pinkie 2.0.4 - MIT -(c) Vsevolod Strukchinsky (http://github.com/floatdrop) -Copyright (c) Vsevolod Strukchinsky +etag 1.8.1 - MIT +https://github.com/jshttp/etag#readme -The MIT License (MIT) +Copyright (c) 2014-2016 Douglas Christopher Wilson -Copyright (c) Vsevolod Strukchinsky (github.com/floatdrop) +(The MIT License) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2014-2016 Douglas Christopher Wilson -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -pinkie-promise 2.0.1 - MIT -https://github.com/floatdrop/pinkie-promise -(c) Vsevolod Strukchinsky (http://github.com/floatdrop) -Copyright (c) Vsevolod Strukchinsky +express 4.17.1 - MIT +http://expressjs.com/ -The MIT License (MIT) +Copyright (c) 2013 Roman Shtylman +Copyright (c) 2009-2013 TJ Holowaychuk +Copyright (c) 2014-2015 Douglas Christopher Wilson +Copyright (c) 2009-2014 TJ Holowaychuk +Copyright (c) 2013-2014 Roman Shtylman +Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) Vsevolod Strukchinsky (github.com/floatdrop) +(The MIT License) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2009-2014 TJ Holowaychuk +Copyright (c) 2013-2014 Roman Shtylman +Copyright (c) 2014-2015 Douglas Christopher Wilson -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -pkg-dir 3.0.0 - MIT -https://github.com/sindresorhus/pkg-dir#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -MIT License +extend 3.0.2 - MIT +https://github.com/justmoon/node-extend#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2014 Stefan Thomas -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The MIT License (MIT) -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Copyright (c) 2014 Stefan Thomas -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -please-upgrade-node 3.2.0 - MIT -https://github.com/typicode/please-upgrade-node#readme -Copyright (c) 2017 +--------------------------------------------------------- -MIT License +extsprintf 1.3.0 - MIT +https://github.com/davepacheco/node-extsprintf + +Copyright (c) 2012, Joyent, Inc. -Copyright (c) 2017 +Copyright (c) 2012, Joyent, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17719,30 +4424,30 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -posix-character-classes 0.1.1 - MIT -https://github.com/jonschlinkert/posix-character-classes -Copyright (c) 2016-2017, Jon Schlinkert -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). +fast-deep-equal 3.1.3 - MIT +https://github.com/epoberezkin/fast-deep-equal#readme -The MIT License (MIT) +Copyright (c) 2017 Evgeny Poberezkin + +MIT License -Copyright (c) 2016-2017, Jon Schlinkert +Copyright (c) 2017 Evgeny Poberezkin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17751,90 +4456,67 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -prettier 1.18.2 - MIT -https://prettier.io -(c) Sindre Sorhus -Copyright (c) 2015 Jon Schlinkert. -Copyright 2011 The Closure Compiler -Copyright (c) Microsoft Corporation. -Copyright (c) 2014-2018, Jon Schlinkert. -Copyright (c) James Long and contributors -Copyright (c) 2014-present, Facebook, Inc. -Copyright (c) 2014 Ivan Nikulin -Copyright 2011 Mozilla Foundation and contributors -Copyright 2014 Mozilla Foundation and contributors -Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell -Copyright Joyent, Inc. and other Node contributors. -Copyright 2009-2011 Mozilla Foundation and contributors -Copyright (c) 2013 Yusuke Suzuki -Copyright (c) 2013-2014 Yusuke Suzuki -Copyright jQuery Foundation and other contributors -Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -Copyright © James Long and contributors -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +fast-json-stable-stringify 2.1.0 - MIT +https://github.com/epoberezkin/fast-json-stable-stringify +Copyright (c) 2013 James Halliday +Copyright (c) 2017 Evgeny Poberezkin -------------------------------------------------------------------- +This software is released under the MIT license: -------------------------------------------------------------------- +Copyright (c) 2017 Evgeny Poberezkin +Copyright (c) 2013 James Halliday -private 0.1.8 - MIT -http://github.com/benjamn/private -Copyright (c) 2014 Ben Newman +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -Copyright (c) 2014 Ben Newman +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +fast-safe-stringify 2.0.7 - MIT +https://github.com/davidmarkclements/fast-safe-stringify#readme -------------------------------------------------------------------- +Copyright (c) 2016 David Mark Clements +Copyright (c) 2017 David Mark Clements & Matteo Collina +Copyright (c) 2018 David Mark Clements, Matteo Collina & Ruben Bridgewater -process-nextick-args 2.0.1 - MIT -https://github.com/calvinmetcalf/process-nextick-args -Copyright (c) 2015 Calvin Metcalf +The MIT License (MIT) -# Copyright (c) 2015 Calvin Metcalf +Copyright (c) 2016 David Mark Clements +Copyright (c) 2017 David Mark Clements & Matteo Collina +Copyright (c) 2018 David Mark Clements, Matteo Collina & Ruben Bridgewater Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17846,26 +4528,27 @@ furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE.** +SOFTWARE. + +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +fecha 2.3.3 - MIT +https://github.com/taylorhakes/fecha -property-expr 1.5.1 - MIT -https://github.com/jquense/expr#readme -Copyright (c) 2014 Jason Quense +Copyright (c) 2015 Taylor Hakes The MIT License (MIT) -Copyright (c) 2014 Jason Quense +Copyright (c) 2015 Taylor Hakes Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -17885,17 +4568,21 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- -proxy-addr 2.0.5 - MIT -https://github.com/jshttp/proxy-addr#readme -Copyright (c) 2014-2016 Douglas Christopher Wilson +--------------------------------------------------------- + +--------------------------------------------------------- + +finalhandler 1.1.2 - MIT +https://github.com/pillarjs/finalhandler#readme + +Copyright (c) 2014-2017 Douglas Christopher Wilson +Copyright (c) 2014-2017 Douglas Christopher Wilson (The MIT License) -Copyright (c) 2014-2016 Douglas Christopher Wilson +Copyright (c) 2014-2017 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -17917,99 +4604,111 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -psl 1.4.0 - MIT -https://github.com/lupomontero/psl#readme -Copyright (c) 2017 Lupo Montero lupomontero@gmail.com -Copyright (c) 2017 Lupo Montero +follow-redirects 1.5.10 - MIT +https://github.com/follow-redirects/follow-redirects -The MIT License (MIT) +Copyright 2014-present Olivier Lalonde , James Talmage , Ruben Verborgh -Copyright (c) 2017 Lupo Montero lupomontero@gmail.com +Copyright 2014–present Olivier Lalonde , James Talmage , Ruben Verborgh -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -pump 3.0.0 - MIT -https://github.com/mafintosh/pump#readme -Copyright (c) 2014 Mathias Buus +form-data 2.3.3 - MIT +https://github.com/form-data/form-data#readme -The MIT License (MIT) +Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors -Copyright (c) 2014 Mathias Buus +Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -punycode 2.1.1 - MIT -https://mths.be/punycode -Copyright Mathias Bynens +--------------------------------------------------------- -Copyright Mathias Bynens +form-data 2.5.1 - MIT +https://github.com/form-data/form-data#readme -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. -------------------------------------------------------------------- + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. -------------------------------------------------------------------- -punycode 1.4.1 - MIT -https://mths.be/punycode -Copyright Mathias Bynens +--------------------------------------------------------- -Copyright Mathias Bynens +--------------------------------------------------------- + +forwarded 0.1.2 - MIT +https://github.com/jshttp/forwarded#readme + +Copyright (c) 2014-2017 Douglas Christopher Wilson + +(The MIT License) + +Copyright (c) 2014-2017 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including +'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -18018,30 +4717,31 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -range-parser 1.2.1 - MIT -https://github.com/jshttp/range-parser#readme -Copyright (c) 2012-2014 TJ Holowaychuk -Copyright (c) 2015-2016 Douglas Christopher Wilson -Copyright (c) 2012-2014 TJ Holowaychuk -Copyright (c) 2015-2016 Douglas Christopher Wilson doug@somethingdoug.com +fresh 0.5.2 - MIT +https://github.com/jshttp/fresh#readme + +Copyright (c) 2012 TJ Holowaychuk +Copyright (c) 2016-2017 Douglas Christopher Wilson +Copyright (c) 2012 TJ Holowaychuk +Copyright (c) 2016-2017 Douglas Christopher Wilson (The MIT License) -Copyright (c) 2012-2014 TJ Holowaychuk -Copyright (c) 2015-2016 Douglas Christopher Wilson +Copyright (c) 2016-2017 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -18063,21 +4763,18 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -raw-body 2.4.0 - MIT -https://github.com/stream-utils/raw-body#readme -Copyright (c) 2013-2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) 2013-2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson +generate-function 2.3.1 - MIT +https://github.com/mafintosh/generate-function + +Copyright (c) 2014 Mathias Buus The MIT License (MIT) -Copyright (c) 2013-2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson +Copyright (c) 2014 Mathias Buus Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18097,40 +4794,17 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- - -------------------------------------------------------------------- - -read-pkg 4.0.1 - MIT -https://github.com/sindresorhus/read-pkg#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -readable-stream 2.3.6 - MIT -https://github.com/nodejs/readable-stream#readme -Copyright Joyent, Inc. and other Node contributors. +--------------------------------------------------------- -Node.js is licensed for use as follows: +getpass 0.1.7 - MIT +https://github.com/arekinath/node-getpass#readme -""" -Copyright Node.js contributors. All rights reserved. +Copyright Joyent, Inc. +Copyright 2016, Joyent, Inc. +Copyright Joyent, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the @@ -18148,51 +4822,72 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -""" -This license applies to parts of Node.js originating from the -https://github.com/joyent/node repository: -""" -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +--------------------------------------------------------- + +har-validator 5.1.5 - MIT +https://github.com/ahmadnassri/node-har-validator + +Copyright (c) 2018 Ahmad Nassri + +MIT License + +Copyright (c) 2018 Ahmad Nassri + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +has-flag 3.0.0 - MIT +https://github.com/sindresorhus/has-flag#readme + +(c) Sindre Sorhus (https://sindresorhus.com) +Copyright (c) Sindre Sorhus (sindresorhus.com) + +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -""" +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +http-errors 1.7.2 - MIT +https://github.com/jshttp/http-errors#readme -readable-stream 3.4.0 - MIT -https://github.com/nodejs/readable-stream#readme -Copyright Joyent, Inc. and other Node contributors. +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2016 Douglas Christopher Wilson +Copyright (c) 2014 Jonathan Ong me@jongleberry.com +Copyright (c) 2016 Douglas Christopher Wilson doug@somethingdoug.com -Node.js is licensed for use as follows: -""" -Copyright Node.js contributors. All rights reserved. +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong me@jongleberry.com +Copyright (c) 2016 Douglas Christopher Wilson doug@somethingdoug.com Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -18202,16 +4897,24 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -""" +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -This license applies to parts of Node.js originating from the -https://github.com/joyent/node repository: -""" -Copyright Joyent, Inc. and other Node contributors. All rights reserved. +--------------------------------------------------------- + +--------------------------------------------------------- + +http-signature 1.2.0 - MIT +https://github.com/joyent/node-http-signature/ + +Copyright Joyent, Inc. +Copyright 2012 Joyent, Inc. +Copyright 2015 Joyent, Inc. +Copyright (c) 2011 Joyent, Inc. + +Copyright Joyent, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the @@ -18229,51 +4932,52 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -""" -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -redeyed 2.1.1 - MIT -https://github.com/thlorenz/redeyed#readme -Copyright 2012 Thorsten Lorenz. +iconv-lite 0.4.24 - MIT +https://github.com/ashtuchkin/iconv-lite -Copyright 2012 Thorsten Lorenz. -All rights reserved. +Copyright (c) Microsoft Corporation. +Copyright (c) 2011 Alexander Shtuchkin -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +Copyright (c) 2011 Alexander Shtuchkin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -regenerate 1.4.0 - MIT -https://mths.be/regenerate -Copyright Mathias Bynens +--------------------------------------------------------- -Copyright Mathias Bynens +iconv-lite 0.5.0 - MIT +https://github.com/ashtuchkin/iconv-lite + +Copyright (c) Microsoft Corporation. +Copyright (c) 2011 Alexander Shtuchkin + +Copyright (c) 2011 Alexander Shtuchkin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -18295,42 +4999,49 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -regenerator-runtime 0.13.3 - MIT -Copyright (c) 2014-present, Facebook, Inc. +--------------------------------------------------------- -MIT License +iconv-lite 0.6.2 - MIT +https://github.com/ashtuchkin/iconv-lite -Copyright (c) 2014-present, Facebook, Inc. +Copyright (c) Microsoft Corporation. +Copyright (c) 2011 Alexander Shtuchkin -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2011 Alexander Shtuchkin -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +inflection 1.12.0 - MIT +https://github.com/dreamerslab/node.inflection#readme -regenerator-runtime 0.11.1 - MIT -Copyright (c) 2014-present, Facebook, Inc. +Copyright (c) 2011 +Copyright (c) 2011 Ben Lin MIT License @@ -18342,18 +5053,16 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -regex-not 1.0.2 - MIT -https://github.com/jonschlinkert/regex-not -Copyright (c) 2016, 2018, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). +ipaddr.js 1.9.0 - MIT +https://github.com/whitequark/ipaddr.js#readme -The MIT License (MIT) +Copyright (c) 2011-2017 -Copyright (c) 2016, 2018, Jon Schlinkert. +Copyright (C) 2011-2017 whitequark Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18362,91 +5071,82 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -regexpu-core 2.0.0 - MIT -https://mths.be/regexpu -Copyright Mathias Bynens +isarray 1.0.0 - MIT +https://github.com/juliangruber/isarray -Copyright Mathias Bynens +Copyright (c) 2013 Julian Gruber -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +MIT License -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Copyright (c) -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -regjsgen 0.2.0 - MIT -https://github.com/d10/regjsgen -Copyright 2014 Benjamin Tan -Copyright 2014 Benjamin Tan (https://d10.github.io/) +--------------------------------------------------------- -Copyright 2014 Benjamin Tan (https://d10.github.io/) +is-arrayish 0.3.2 - MIT +https://github.com/qix-/node-is-arrayish#readme -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Copyright (c) 2015 JD Ballard -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The MIT License (MIT) -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Copyright (c) 2015 JD Ballard + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -repeat-element 1.1.3 - MIT -https://github.com/jonschlinkert/repeat-element -Copyright (c) 2015-present, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). +is-buffer 2.0.3 - MIT +https://github.com/feross/is-buffer#readme + +Copyright (c) Feross Aboukhadijeh +Copyright (c) Feross Aboukhadijeh (http://feross.org). The MIT License (MIT) -Copyright (c) 2015-present, Jon Schlinkert. +Copyright (c) Feross Aboukhadijeh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18467,19 +5167,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +is-property 1.0.2 - MIT +https://github.com/mikolalysenko/is-property -------------------------------------------------------------------- +(c) 2013 Mikola Lysenko. +Copyright (c) 2013 Mikola Lysenko -repeat-string 1.6.1 - MIT -https://github.com/jonschlinkert/repeat-string -Copyright (c) 2014-2015, Jon Schlinkert. -Copyright (c) 2014-2016, Jon Schlinkert. -Copyright (c) 2016, Jon Schlinkert (http://github.com/jonschlinkert). The MIT License (MIT) -Copyright (c) 2014-2016, Jon Schlinkert. +Copyright (c) 2013 Mikola Lysenko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18500,12 +5201,36 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- + +--------------------------------------------------------- + +isstream 0.1.2 - MIT +https://github.com/rvagg/isstream + +Copyright (c) 2015 Rod Vagg +Copyright (c) 2015 Rod Vagg rvagg (https://twitter.com/rvagg) + +The MIT License (MIT) +===================== + +Copyright (c) 2015 Rod Vagg +--------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +is-stream 1.1.0 - MIT +https://github.com/sindresorhus/is-stream#readme -repeating 2.0.1 - MIT -https://github.com/sindresorhus/repeating#readme (c) Sindre Sorhus (https://sindresorhus.com) Copyright (c) Sindre Sorhus (sindresorhus.com) @@ -18532,81 +5257,98 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -resolve 1.12.0 - MIT -https://github.com/browserify/resolve#readme -Copyright (c) 2012 James Halliday +is-typedarray 1.0.0 - MIT +https://github.com/hughsk/is-typedarray -MIT License -Copyright (c) 2012 James Halliday +This software is released under the MIT license: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -resolve-from 3.0.0 - MIT -https://github.com/sindresorhus/resolve-from#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +jsbn 0.1.1 - MIT +https://github.com/andyperlitch/jsbn#readme -The MIT License (MIT) +Copyright (c) 2005 Tom Wu +Copyright (c) 2003-2005 Tom Wu +Copyright (c) 2005-2009 Tom Wu -Copyright (c) Sindre Sorhus (sindresorhus.com) +Licensing +--------- -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +This software is covered under the following copyright: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +/* + * Copyright (c) 2003-2005 Tom Wu + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF + * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * In addition, the following condition applies: + * + * All redistributions must retain an intact copy of this copyright notice + * and disclaimer. + */ -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Address all questions regarding this license to: + Tom Wu + tjw@cs.Stanford.EDU -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -resolve-url 0.2.1 - MIT -https://github.com/lydell/resolve-url -Copyright (c) 2013 Simon Lydell -Copyright 2014 Simon Lydell X11 +json-schema-traverse 0.4.1 - MIT +https://github.com/epoberezkin/json-schema-traverse#readme -The MIT License (MIT) +Copyright (c) 2017 Evgeny Poberezkin -Copyright (c) 2013 Simon Lydell +MIT License + +Copyright (c) 2017 Evgeny Poberezkin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18615,59 +5357,60 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -restore-cursor 2.0.0 - MIT -https://github.com/sindresorhus/restore-cursor#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -The MIT License (MIT) +jsonwebtoken 8.5.1 - MIT +https://github.com/auth0/node-jsonwebtoken#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2015 Auth0, Inc. (http://auth0.com) +The MIT License (MIT) + +Copyright (c) 2015 Auth0, Inc. (http://auth0.com) + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +jsprim 1.4.1 - MIT +https://github.com/joyent/node-jsprim#readme -ret 0.1.15 - MIT -https://github.com/fent/ret.js#readme -Copyright (c) 2011 by Roly Fentanes +Copyright (c) 2012, Joyent, Inc. -Copyright (C) 2011 by Roly Fentanes +Copyright (c) 2012, Joyent, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18685,55 +5428,76 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -retry-as-promised 3.2.0 - MIT -https://github.com/mickhansen/retry-as-promised -Copyright (c) 2015-2016 Mick Hansen. http://mhansen.io +jwa 1.4.1 - MIT +https://github.com/brianloveswords/node-jwa#readme -The MIT License +Copyright (c) 2013 Brian J. Brennan -Copyright (c) 2015-2016 Mick Hansen. http://mhansen.io +Copyright (c) 2013 Brian J. Brennan -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- + +jws 3.2.2 - MIT +https://github.com/brianloveswords/node-jws#readme -------------------------------------------------------------------- +Copyright (c) 2013 Brian J. Brennan +Copyright (c) 2013-2015 Brian J. Brennan -------------------------------------------------------------------- +Copyright (c) 2013 Brian J. Brennan -run-node 1.0.0 - MIT -https://github.com/sindresorhus/run-node#readme -(c) Sindre Sorhus -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -MIT License +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -Copyright (c) Sindre Sorhus (sindresorhus.com) +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +kuler 1.0.1 - MIT +https://github.com/3rd-Eden/kuler + +Copyright 2014 Arnout Kazemier + +Copyright 2014 Arnout Kazemier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: @@ -18742,18 +5506,19 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -safe-buffer 5.1.2 - MIT -https://github.com/feross/safe-buffer -Copyright (c) Feross Aboukhadijeh -Copyright (c) Feross Aboukhadijeh (http://feross.org) +leven 2.1.0 - MIT +https://github.com/sindresorhus/leven#readme + +(c) Sindre Sorhus (https://sindresorhus.com) +Copyright (c) Sindre Sorhus (sindresorhus.com) The MIT License (MIT) -Copyright (c) Feross Aboukhadijeh +Copyright (c) Sindre Sorhus (sindresorhus.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18774,108 +5539,94 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -safe-regex 1.1.0 - MIT -https://github.com/substack/safe-regex +--------------------------------------------------------- -This software is released under the MIT license: - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +lodash 4.17.19 - MIT +https://lodash.com/ -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Copyright OpenJS Foundation and other contributors +Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +Copyright OpenJS Foundation and other contributors -------------------------------------------------------------------- +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors -------------------------------------------------------------------- +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash -safer-buffer 2.1.2 - MIT -https://github.com/ChALkeR/safer-buffer#readme -Copyright (c) 2018 Nikita Skovoroda +The following license applies to all parts of this software except as +documented below: -MIT License +==== -Copyright (c) 2018 Nikita Skovoroda +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +==== +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. -------------------------------------------------------------------- +CC0: http://creativecommons.org/publicdomain/zero/1.0/ -------------------------------------------------------------------- +==== -semver-compare 1.0.0 - MIT -https://github.com/substack/semver-compare +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. -This software is released under the MIT license: -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +lodash.includes 4.3.0 - MIT +https://lodash.com/ +Copyright jQuery Foundation and other contributors +Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -------------------------------------------------------------------- +Copyright jQuery Foundation and other contributors -------------------------------------------------------------------- +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors -send 0.17.1 - MIT -https://github.com/pillarjs/send#readme -Copyright (c) 2012 TJ Holowaychuk -Copyright (c) 2014-2016 Douglas Christopher Wilson +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash -(The MIT License) +The following license applies to all parts of this software except as +documented below: -Copyright (c) 2012 TJ Holowaychuk -Copyright (c) 2014-2016 Douglas Christopher Wilson +==== Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including +"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -18884,30 +5635,48 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +==== -------------------------------------------------------------------- +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. -------------------------------------------------------------------- +CC0: http://creativecommons.org/publicdomain/zero/1.0/ -seq-queue 0.0.5 - MIT -https://github.com/changchang/seq-queue -Copyright (c) 2012 Netease, Inc. +==== -(The MIT License) +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. -Copyright (c) 2012 Netease, Inc. and other pomelo contributors + +--------------------------------------------------------- + +--------------------------------------------------------- + +lodash.isboolean 3.0.3 - MIT +https://lodash.com/ + +Copyright 2012-2016 The Dojo Foundation +Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + +Copyright 2012-2016 The Dojo Foundation +Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including +"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -18916,62 +5685,43 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -sequelize 5.18.4 - MIT -https://sequelize.org/ -Copyright (c) 2014-present Sequelize - -MIT License +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -Copyright (c) 2014-present Sequelize contributors -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +lodash.isinteger 4.0.4 - MIT +https://lodash.com/ +Copyright jQuery Foundation and other contributors +Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -------------------------------------------------------------------- +Copyright jQuery Foundation and other contributors -------------------------------------------------------------------- +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors -sequelize-pool 2.3.0 - MIT -https://github.com/sushantdhiman/sequelize-pool#readme -Copyright (c) 2010-2016 James Cooper -Copyright (c) 2018-present Sushant +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash -(The MIT License) +The following license applies to all parts of this software except as +documented below: -Copyright (c) 2018-present Sushant +==== Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including +"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -18980,26 +5730,48 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +==== --------------------------------- +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. -(Original Fork License) +CC0: http://creativecommons.org/publicdomain/zero/1.0/ -[generic-pool@2.5] +==== -Copyright (c) 2010-2016 James Cooper +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +lodash.isnumber 3.0.3 - MIT +https://lodash.com/ + +Copyright 2012-2016 The Dojo Foundation +Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + +Copyright 2012-2016 The Dojo Foundation +Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including +"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -19008,36 +5780,43 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -serve-static 1.14.1 - MIT -https://github.com/expressjs/serve-static#readme -Copyright (c) 2011 LearnBoost -Copyright (c) 2010 Sencha Inc. -Copyright (c) 2011 TJ Holowaychuk -Copyright (c) 2014-2016 Douglas Christopher Wilson +lodash.isplainobject 4.0.6 - MIT +https://lodash.com/ -(The MIT License) +Copyright jQuery Foundation and other contributors +Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -Copyright (c) 2010 Sencha Inc. -Copyright (c) 2011 LearnBoost -Copyright (c) 2011 TJ Holowaychuk -Copyright (c) 2014-2016 Douglas Christopher Wilson +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including +"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -19046,131 +5825,137 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -set-value 2.0.1 - MIT -https://github.com/jonschlinkert/set-value -Copyright (c) 2014-2017, Jon Schlinkert -Copyright (c) 2014-2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). +==== -The MIT License (MIT) +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. -Copyright (c) 2014-2017, Jon Schlinkert +CC0: http://creativecommons.org/publicdomain/zero/1.0/ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +==== -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +lodash.isstring 4.0.1 - MIT +https://lodash.com/ -shebang-command 1.2.0 - MIT -https://github.com/kevva/shebang-command#readme -(c) Kevin Martensson (http://github.com/kevva) -Copyright (c) Kevin Martensson +Copyright 2012-2016 The Dojo Foundation +Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -The MIT License (MIT) +Copyright 2012-2016 The Dojo Foundation +Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors -Copyright (c) Kevin Martensson (github.com/kevva) +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +lodash.once 4.1.1 - MIT +https://lodash.com/ -shebang-command 2.0.0 - MIT -https://github.com/kevva/shebang-command#readme -Copyright (c) Kevin Martensson +Copyright jQuery Foundation and other contributors +Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -MIT License +Copyright jQuery Foundation and other contributors -Copyright (c) Kevin Mårtensson (github.com/kevva) +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The following license applies to all parts of this software except as +documented below: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +==== +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -------------------------------------------------------------------- +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -shebang-regex 3.0.0 - MIT -https://github.com/sindresorhus/shebang-regex#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +==== -MIT License +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. -Copyright (c) Sindre Sorhus (sindresorhus.com) +CC0: http://creativecommons.org/publicdomain/zero/1.0/ -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +==== -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +logform 2.1.2 - MIT +https://github.com/winstonjs/logform#readme -shebang-regex 1.0.0 - MIT -https://github.com/sindresorhus/shebang-regex -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2017 Charlie Robbins & the Contributors. -The MIT License (MIT) +MIT License -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2017 Charlie Robbins & the Contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19179,129 +5964,122 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -simple-git 1.126.0 - MIT -https://github.com/steveukx/git-js#readme -Copyright (c) 2015 Steve King - -The MIT License (MIT) +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -Copyright (c) 2015 Steve King -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +lokijs 1.5.11 - MIT +https://techfort.github.io/LokiJS/ +Copyright (c) 2015 TechFort -------------------------------------------------------------------- +Copyright (c) 2015 TechFort -------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -simple-swizzle 0.2.2 - MIT -https://github.com/qix-/node-simple-swizzle#readme -Copyright (c) 2015 Josh Junon +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -The MIT License (MIT) +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -Copyright (c) 2015 Josh Junon -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +--------------------------------------------------------- -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +media-typer 0.3.0 - MIT +https://github.com/jshttp/media-typer +Copyright (c) 2014 Douglas Christopher Wilson -------------------------------------------------------------------- +(The MIT License) -------------------------------------------------------------------- +Copyright (c) 2014 Douglas Christopher Wilson -slash 2.0.0 - MIT -https://github.com/sindresorhus/slash#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -MIT License +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -Copyright (c) Sindre Sorhus (sindresorhus.com) +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +merge-descriptors 1.0.1 - MIT +https://github.com/component/merge-descriptors -------------------------------------------------------------------- +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson +Copyright (c) 2013 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson -------------------------------------------------------------------- +(The MIT License) -slash 1.0.0 - MIT -https://github.com/sindresorhus/slash -(c) Sindre Sorhus (http://sindresorhus.com) +Copyright (c) 2013 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson -MIT License +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -Copyright (c) +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +methods 1.1.2 - MIT +https://github.com/jshttp/methods -slice-ansi 0.0.4 - MIT -https://github.com/chalk/slice-ansi#readme -(c) 2015 DC -(c) David Caccavella (https://githbu.com/dthree) +Copyright (c) 2013-2014 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson +Copyright (c) 2013-2014 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson (The MIT License) -Copyright (c) 2015 DC +Copyright (c) 2013-2014 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -19322,51 +6100,20 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -snapdragon 0.8.2 - MIT -https://github.com/jonschlinkert/snapdragon -Copyright (c) 2015-2016, Jon Schlinkert. -Copyright (c) 2012 TJ Holowaychuk -Copyright (c) 2016, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015-2016, Jon Schlinkert. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +mime 1.6.0 - MIT +https://github.com/broofa/node-mime#readme -snapdragon-node 2.1.1 - MIT -https://github.com/jonschlinkert/snapdragon-node -Copyright (c) 2017, Jon Schlinkert -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer The MIT License (MIT) -Copyright (c) 2017, Jon Schlinkert +Copyright (c) 2010 Benjamin Thomas, Robert Kieffer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19387,53 +6134,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -snapdragon-util 3.0.1 - MIT -https://github.com/jonschlinkert/snapdragon-util -Copyright (c) 2017, Jon Schlinkert -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +mime-db 1.40.0 - MIT +https://github.com/jshttp/mime-db#readme -------------------------------------------------------------------- +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014 Jonathan Ong me@jongleberry.com -source-map-resolve 0.5.2 - MIT -https://github.com/lydell/source-map-resolve#readme -Copyright 2014 Simon Lydell X11 -Copyright 2017 Simon Lydell X11 -Copyright 2014, 2017 Simon Lydell X11 -Copyright (c) 2014, 2015, 2016, 2017 Simon Lydell -Copyright 2014, 2015, 2016, 2017 Simon Lydell X11 The MIT License (MIT) -Copyright (c) 2014, 2015, 2016, 2017 Simon Lydell +Copyright (c) 2014 Jonathan Ong me@jongleberry.com Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19454,124 +6168,35 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -source-map-support 0.4.18 - MIT -https://github.com/evanw/node-source-map-support#readme -Copyright (c) 2014 Evan Wallace - -The MIT License (MIT) - -Copyright (c) 2014 Evan Wallace - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -source-map-support 0.5.13 - MIT -https://github.com/evanw/node-source-map-support#readme -Copyright (c) 2014 Evan Wallace - -The MIT License (MIT) - -Copyright (c) 2014 Evan Wallace - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -source-map-url 0.4.0 - MIT -https://github.com/lydell/source-map-url#readme -Copyright (c) 2014 Simon Lydell -Copyright 2014 Simon Lydell X11 - -The MIT License (MIT) - -Copyright (c) 2014 Simon Lydell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +mime-types 2.1.24 - MIT +https://github.com/jshttp/mime-types#readme -spdx-expression-parse 3.0.0 - MIT -https://github.com/jslicense/spdx-expression-parse.js#readme -Copyright (c) 2015 Kyle E. Mitchell +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson -The MIT License +(The MIT License) -Copyright (c) 2015 Kyle E. Mitchell & other authors listed in AUTHORS +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including +'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY @@ -19580,139 +6205,121 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -split-string 3.1.0 - MIT -https://github.com/jonschlinkert/split-string -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) +--------------------------------------------------------- -Copyright (c) 2015-2017, Jon Schlinkert. +--------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +moment 2.28.0 - MIT +https://momentjs.com/ -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Copyright (c) JS Foundation and other contributors -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Copyright (c) JS Foundation and other contributors +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: -------------------------------------------------------------------- +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -sqlstring 2.3.1 - MIT -https://github.com/mysqljs/sqlstring#readme -Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors -Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors +--------------------------------------------------------- - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: +--------------------------------------------------------- - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. +moment-timezone 0.5.31 - MIT +http://momentjs.com/timezone/ - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. +Copyright (c) JS Foundation and other contributors +The MIT License (MIT) -------------------------------------------------------------------- +Copyright (c) JS Foundation and other contributors -------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -sshpk 1.16.1 - MIT -https://github.com/arekinath/node-sshpk#readme -Copyright Joyent, Inc. -Copyright 2015 Joyent, Inc. -Copyright 2016 Joyent, Inc. -Copyright 2017 Joyent, Inc. -Copyright 2018 Joyent, Inc. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -Copyright Joyent, Inc. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. +--------------------------------------------------------- +morgan 1.10.0 - MIT +https://github.com/expressjs/morgan#readme -------------------------------------------------------------------- +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2011 TJ Holowaychuk +Copyright (c) 2014-2017 Douglas Christopher Wilson +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2017 Douglas Christopher Wilson -------------------------------------------------------------------- +(The MIT License) -stack-trace 0.0.10 - MIT -https://github.com/felixge/node-stack-trace -Copyright (c) 2011 Felix Geisendorfer (felix@debuggable.com) +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2017 Douglas Christopher Wilson -Copyright (c) 2011 Felix Geisendörfer (felix@debuggable.com) +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +mri 1.1.4 - MIT +https://github.com/lukeed/mri#readme -static-extend 0.1.2 - MIT -https://github.com/jonschlinkert/static-extend -Copyright (c) 2016, Jon Schlinkert. +(c) Luke Edwards (https://lukeed.com) +Copyright (c) Luke Edwards (lukeed.com) The MIT License (MIT) -Copyright (c) 2016, Jon Schlinkert. +Copyright (c) Luke Edwards (lukeed.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19733,22 +6340,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -statuses 1.5.0 - MIT -https://github.com/jshttp/statuses#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2016 Douglas Christopher Wilson -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2016 Douglas Christopher Wilson +ms 2.0.0 - MIT +https://github.com/zeit/ms#readme +Copyright (c) 2016 Zeit, Inc. The MIT License (MIT) -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2016 Douglas Christopher Wilson +Copyright (c) 2016 Zeit, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19757,156 +6360,156 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -string_decoder 1.1.1 - MIT -https://github.com/nodejs/string_decoder -Copyright Joyent, Inc. and other Node contributors. +ms 2.1.1 - MIT +https://github.com/zeit/ms#readme -Node.js is licensed for use as follows: +Copyright (c) 2016 Zeit, Inc. -""" -Copyright Node.js contributors. All rights reserved. +The MIT License (MIT) + +Copyright (c) 2016 Zeit, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -""" - -This license applies to parts of Node.js originating from the -https://github.com/joyent/node repository: +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -""" -Copyright Joyent, Inc. and other Node contributors. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. -""" +--------------------------------------------------------- +ms 2.1.2 - MIT +https://github.com/zeit/ms#readme +Copyright (c) 2016 Zeit, Inc. -------------------------------------------------------------------- +The MIT License (MIT) -------------------------------------------------------------------- +Copyright (c) 2016 Zeit, Inc. -string-argv 0.0.2 - MIT -https://github.com/mccormicka/string-argv +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -MIT License +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -Copyright (c) +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +multistream 2.1.1 - MIT +https://github.com/feross/multistream -------------------------------------------------------------------- +Copyright (c) Feross Aboukhadijeh +Copyright (c) Feross Aboukhadijeh (http://feross.org). -string-width 2.1.1 - MIT -https://github.com/sindresorhus/string-width#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +The MIT License (MIT) -MIT License +Copyright (c) Feross Aboukhadijeh -Copyright (c) Sindre Sorhus (sindresorhus.com) +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +mysql2 2.1.0 - MIT +https://github.com/sidorares/node-mysql2#readme -string-width 1.0.2 - MIT -https://github.com/sindresorhus/string-width#readme -(c) Sindre Sorhus (https://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2016 Andrey Sidorov (sidorares@yandex.ru) and contributors -The MIT License (MIT) +Copyright (c) 2016 Andrey Sidorov (sidorares@yandex.ru) and contributors -Copyright (c) Sindre Sorhus (sindresorhus.com) + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +named-placeholders 1.1.2 - MIT +https://github.com/sidorares/named-placeholders#readme -string.prototype.trimleft 2.1.0 - MIT -https://github.com/es-shims/String.prototype.trimLeft#readme -Copyright (c) 2015 Jordan Harband +Copyright (c) 2014 Andrey Sidorov The MIT License (MIT) -Copyright (c) 2015 Jordan Harband +Copyright (c) 2014 Andrey Sidorov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19927,18 +6530,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +native-duplexpair 1.0.0 - MIT +https://github.com/tediousjs/native-duplexpair#readme -string.prototype.trimright 2.1.0 - MIT -https://github.com/es-shims/String.prototype.trimRight#readme -Copyright (c) 2015 Jordan Harband +Copyright (c) 2017 Anna Henningsen The MIT License (MIT) -Copyright (c) 2015 Jordan Harband +Copyright (c) 2017 Anna Henningsen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19960,37 +6563,59 @@ SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -strip-ansi 4.0.0 - MIT -https://github.com/chalk/strip-ansi#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) +negotiator 0.6.2 - MIT +https://github.com/jshttp/negotiator#readme -MIT License +Copyright (c) 2012 Federico Romero +Copyright (c) 2014 Federico Romero +Copyright (c) 2012 Isaac Z. Schlueter +Copyright (c) 2012-2014 Federico Romero +Copyright (c) 2012-2014 Isaac Z. Schlueter +Copyright (c) 2015 Douglas Christopher Wilson +Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) Sindre Sorhus (sindresorhus.com) +(The MIT License) -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) 2012-2014 Federico Romero +Copyright (c) 2012-2014 Isaac Z. Schlueter +Copyright (c) 2014-2015 Douglas Christopher Wilson -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +one-time 0.0.4 - MIT +https://github.com/unshiftio/one-time -strip-ansi 3.0.1 - MIT -https://github.com/chalk/strip-ansi -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2015 Unshift.io, Arnout Kazemier The MIT License (MIT) -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2015 Unshift.io, Arnout Kazemier, the Contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19999,95 +6624,135 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -strip-eof 1.0.0 - MIT -https://github.com/sindresorhus/strip-eof -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -The MIT License (MIT) +on-finished 2.3.0 - MIT +https://github.com/jshttp/on-finished -Copyright (c) Sindre Sorhus (sindresorhus.com) +Copyright (c) 2013 Jonathan Ong +Copyright (c) 2014 Douglas Christopher Wilson +Copyright (c) 2013 Jonathan Ong +Copyright (c) 2014 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +(The MIT License) -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Copyright (c) 2013 Jonathan Ong +Copyright (c) 2014 Douglas Christopher Wilson -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -supports-color 5.5.0 - MIT -https://github.com/chalk/supports-color#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -MIT License +--------------------------------------------------------- -Copyright (c) Sindre Sorhus (sindresorhus.com) +on-headers 1.0.2 - MIT +https://github.com/jshttp/on-headers#readme -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) 2014 Douglas Christopher Wilson -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +(The MIT License) -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Copyright (c) 2014 Douglas Christopher Wilson +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -------------------------------------------------------------------- +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -supports-color 5.4.0 - MIT -https://github.com/chalk/supports-color#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) -MIT License +--------------------------------------------------------- -Copyright (c) Sindre Sorhus (sindresorhus.com) +--------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +parseurl 1.3.3 - MIT +https://github.com/pillarjs/parseurl#readme -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2017 Douglas Christopher Wilson +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2017 Douglas Christopher Wilson -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2017 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -supports-color 2.0.0 - MIT -https://github.com/chalk/supports-color -(c) Sindre Sorhus (http://sindresorhus.com) +path-is-absolute 1.0.1 - MIT +https://github.com/sindresorhus/path-is-absolute#readme + +(c) Sindre Sorhus (https://sindresorhus.com) Copyright (c) Sindre Sorhus (sindresorhus.com) The MIT License (MIT) @@ -20113,19 +6778,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -symbol-observable 1.2.0 - MIT -https://github.com/blesh/symbol-observable#readme -Copyright (c) Ben Lesh -Copyright (c) Sindre Sorhus (sindresorhus.com) +path-to-regexp 0.1.7 - MIT +https://github.com/component/path-to-regexp#readme + +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) The MIT License (MIT) -Copyright (c) Sindre Sorhus (sindresorhus.com) -Copyright (c) Ben Lesh +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -20146,48 +6810,34 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- - -tedious 6.6.5 - MIT -https://github.com/tediousjs/tedious -Copyright (c) 2010-2018 Mike D Pilsbury +--------------------------------------------------------- -The MIT License +performance-now 2.1.0 - MIT +https://github.com/braveg1rl/performance-now -Copyright (c) 2010-2018 Mike D Pilsbury +Copyright (c) 2013 Braveg1rl +Copyright (c) 2017 Braveg1rl -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Copyright (c) 2013 Braveg1rl -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -text-hex 1.0.0 - MIT -https://github.com/3rd-Eden/text-hex -Copyright (c) 2014-2015 Arnout Kazemier +process-nextick-args 2.0.1 - MIT +https://github.com/calvinmetcalf/process-nextick-args -The MIT License (MIT) +Copyright (c) 2015 Calvin Metcalf -Copyright (c) 2014-2015 Arnout Kazemier +# Copyright (c) 2015 Calvin Metcalf Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -20199,93 +6849,153 @@ furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE.** + + +--------------------------------------------------------- + +--------------------------------------------------------- + +proxy-addr 2.0.5 - MIT +https://github.com/jshttp/proxy-addr#readme + +Copyright (c) 2014-2016 Douglas Christopher Wilson + +(The MIT License) + +Copyright (c) 2014-2016 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +psl 1.4.0 - MIT +https://github.com/lupomontero/psl#readme -tmp 0.0.29 - MIT -http://github.com/raszi/node-tmp -Copyright (c) 2014 KARASZI Istvan -Copyright (c) 2011-2015 KARASZI Istvan +Copyright (c) 2017 Lupo Montero lupomontero@gmail.com +Copyright (c) 2017 Lupo Montero The MIT License (MIT) -Copyright (c) 2014 KARASZI István +Copyright (c) 2017 Lupo Montero lupomontero@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +punycode 2.1.1 - MIT +https://mths.be/punycode + +Copyright Mathias Bynens + +Copyright Mathias Bynens + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +range-parser 1.2.1 - MIT +https://github.com/jshttp/range-parser#readme -------------------------------------------------------------------- +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson doug@somethingdoug.com -to-fast-properties 1.0.3 - MIT -https://github.com/sindresorhus/to-fast-properties#readme -(c) Petka Antonov, Sindre Sorhus -Copyright (c) 2014 Petka Antonov 2015 Sindre Sorhus +(The MIT License) -The MIT License (MIT) +Copyright (c) 2012-2014 TJ Holowaychuk +Copyright (c) 2015-2016 Douglas Christopher Wilson +Copyright (c) 2014-2015 Douglas Christopher Wilson The MIT License (MIT) -Copyright (c) 2015-2016, Jon Schlinkert. +Copyright (c) 2013-2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -20306,24 +7016,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +readable-stream 2.3.6 - MIT +https://github.com/nodejs/readable-stream#readme -to-regex 3.0.2 - MIT -https://github.com/jonschlinkert/to-regex -Copyright (c) 2016-2018, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). +Copyright Joyent, Inc. and other Node contributors. -The MIT License (MIT) +Node.js is licensed for use as follows: -Copyright (c) 2016-2018, Jon Schlinkert. +""" +Copyright Node.js contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -20333,30 +7044,21 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -to-regex-range 2.1.1 - MIT -https://github.com/micromatch/to-regex-range -Copyright (c) 2015-2017, Jon Schlinkert -Copyright (c) 2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" -Copyright (c) 2015-2017, Jon Schlinkert +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -20366,60 +7068,55 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -toidentifier 1.0.0 - MIT -https://github.com/component/toidentifier#readme -Copyright (c) 2016 Douglas Christopher Wilson -Copyright (c) 2016 Douglas Christopher Wilson +readable-stream 3.4.0 - MIT +https://github.com/nodejs/readable-stream#readme -MIT License +Copyright Joyent, Inc. and other Node contributors. -Copyright (c) 2016 Douglas Christopher Wilson +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -toposort 2.0.2 - MIT -https://github.com/marcelklehr/toposort#readme -Copyright (c) 2012 by Marcel Klehr +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: -Toposort - Topological sorting for node.js -Copyright (c) 2012 by Marcel Klehr -MIT LICENSE +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -20429,60 +7126,55 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -toposort-class 1.0.1 - MIT -https://github.com/gustavohenke/toposort#readme -Copyright (c) 2015 Gustavo Henke and Aaron Trent +readable-stream 3.6.0 - MIT +https://github.com/nodejs/readable-stream#readme -The MIT License (MIT) +Copyright Joyent, Inc. and other Node contributors. -Copyright (c) 2015 Gustavo Henke and Aaron Trent +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -trim-right 1.0.1 - MIT -https://github.com/sindresorhus/trim-right -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" -Copyright (c) Sindre Sorhus (sindresorhus.com) +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -20492,54 +7184,58 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -triple-beam 1.3.0 - MIT -https://github.com/winstonjs/triple-beam#readme -Copyright (c) 2017 -(c) 2010 Charlie Robbins +redeyed 2.1.1 - MIT +https://github.com/thlorenz/redeyed#readme -MIT License +Copyright 2012 Thorsten Lorenz. -Copyright (c) 2017 winstonjs +Copyright 2012 Thorsten Lorenz. +All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +retry-as-promised 3.2.0 - MIT +https://github.com/mickhansen/retry-as-promised -ts-node 7.0.1 - MIT -https://github.com/TypeStrong/ts-node -Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) +Copyright (c) 2015-2016 Mick Hansen. http://mhansen.io -The MIT License (MIT) +The MIT License -Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) +Copyright (c) 2015-2016 Mick Hansen. http://mhansen.io Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -20560,48 +7256,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- - -tsutils 2.29.0 - MIT -https://github.com/ajafff/tsutils#readme -Copyright (c) 2017 Klaus Meinhardt - -The MIT License (MIT) - -Copyright (c) 2017 Klaus Meinhardt - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +safe-buffer 5.1.2 - MIT +https://github.com/feross/safe-buffer -tunnel 0.0.6 - MIT -https://github.com/koichik/node-tunnel/ -Copyright (c) 2012 Koichi Kobayashi +Copyright (c) Feross Aboukhadijeh +Copyright (c) Feross Aboukhadijeh (http://feross.org) The MIT License (MIT) -Copyright (c) 2012 Koichi Kobayashi +Copyright (c) Feross Aboukhadijeh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -20622,17 +7291,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -tunnel 0.0.4 - MIT -https://github.com/koichik/node-tunnel/ -Copyright (c) 2012 Koichi Kobayashi +safer-buffer 2.1.2 - MIT +https://github.com/ChALkeR/safer-buffer#readme -The MIT License (MIT) +Copyright (c) 2018 Nikita Skovoroda -Copyright (c) 2012 Koichi Kobayashi +MIT License + +Copyright (c) 2018 Nikita Skovoroda Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -20641,33 +7311,32 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -type-is 1.6.18 - MIT -https://github.com/jshttp/type-is#readme -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson +send 0.17.1 - MIT +https://github.com/pillarjs/send#readme + +Copyright (c) 2012 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson (The MIT License) -Copyright (c) 2014 Jonathan Ong -Copyright (c) 2014-2015 Douglas Christopher Wilson +Copyright (c) 2012 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -20689,74 +7358,22 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -typed-rest-client 1.2.0 - MIT -https://github.com/Microsoft/typed-rest-client#readme -Copyright (c) Microsoft. -Copyright (c) 2015 Zhiye Li -Copyright (c) 2016 Zeit, Inc. -Copyright (c) 2014 Tyler Kellen -Copyright (c) 2015 Tyler Kellen -Copyright (c) Isaac Z. Schlueter -Copyright (c) 2012 Koichi Kobayashi -Copyright (c) Microsoft Corporation. -Copyright (c) 2011-2017 JS Foundation -Copyright (c) Isaac Z. Schlueter and Contributors -Copyright 2010 James Halliday (mail@substack.net) -Copyright Joyent, Inc. and other Node contributors. -Copyright (c) 2012, Artur Adib -Copyright Mathias Bynens -Copyright (c) 2011 TJ Holowaychuk -Copyright (c) 2014 TJ Holowaychuk -Copyright (c) 2009-2015, Kevin Decker -Copyright (c) 2013 Julian Gruber -Copyright (c) 2012-2014 Kit Cambridge. http://kitcambridge.be -Copyright 2012-2015 The Dojo Foundation -Copyright (c) Sindre Sorhus (sindresorhus.com) -Copyright jQuery Foundation and other contributors -Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - -Typed Rest Client for Node.js - -Copyright (c) Microsoft Corporation - -All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +seq-queue 0.0.5 - MIT +https://github.com/changchang/seq-queue -------------------------------------------------------------------- +Copyright (c) 2012 Netease, Inc. -uc.micro 1.0.6 - MIT -https://github.com/markdown-it/uc.micro#readme -Copyright Mathias Bynens +(The MIT License) -Copyright Mathias Bynens +Copyright (c) 2012 Netease, Inc. and other pomelo contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including +'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to @@ -20765,61 +7382,27 @@ the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -underscore 1.8.3 - MIT -http://underscorejs.org -Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -(c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Underscore - -Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative -Reporters & Editors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +sequelize 6.3.5 - MIT +https://sequelize.org/ -union-value 1.0.1 - MIT -https://github.com/jonschlinkert/union-value -Copyright (c) 2015-2017, Jon Schlinkert -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). +Copyright (c) 2014-present Sequelize -The MIT License (MIT) +MIT License -Copyright (c) 2015-2017, Jon Schlinkert +Copyright (c) 2014-present Sequelize contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -20828,30 +7411,31 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -unpipe 1.0.0 - MIT -https://github.com/stream-utils/unpipe -Copyright (c) 2015 Douglas Christopher Wilson -Copyright (c) 2015 Douglas Christopher Wilson +sequelize-pool 6.1.0 - MIT +https://github.com/sushantdhiman/sequelize-pool#readme + +Copyright (c) 2010-2016 James Cooper +Copyright (c) 2018-present Sushant (The MIT License) -Copyright (c) 2015 Douglas Christopher Wilson +Copyright (c) 2018-present Sushant Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -20873,100 +7457,85 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -unset-value 1.0.0 - MIT -https://github.com/jonschlinkert/unset-value -Copyright (c) 2015, 2017, Jon Schlinkert. -Copyright (c) 2017, Jon Schlinkert (https://github.com/jonschlinkert). - -The MIT License (MIT) - -Copyright (c) 2015, 2017, Jon Schlinkert - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +-------------------------------- +(Original Fork License) -------------------------------------------------------------------- +[generic-pool@2.5] -------------------------------------------------------------------- +Copyright (c) 2010-2016 James Cooper -urix 0.1.0 - MIT -https://github.com/lydell/urix -Copyright (c) 2013 Simon Lydell -Copyright 2014 Simon Lydell X11 +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -The MIT License (MIT) +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -Copyright (c) 2013 Simon Lydell +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- +serve-static 1.14.1 - MIT +https://github.com/expressjs/serve-static#readme -------------------------------------------------------------------- +Copyright (c) 2011 LearnBoost +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson -------------------------------------------------------------------- +(The MIT License) -url-join 1.1.0 - MIT -https://github.com/jfromaniello/url-join#readme +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson -MIT License +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -Copyright (c) +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +simple-swizzle 0.2.2 - MIT +https://github.com/qix-/node-simple-swizzle#readme -use 3.1.1 - MIT -https://github.com/jonschlinkert/use -Copyright (c) 2015-2017, Jon Schlinkert. -Copyright (c) 2015-present, Jon Schlinkert. -Copyright (c) 2018, Jon Schlinkert (https://github.com/jonschlinkert). +Copyright (c) 2015 Josh Junon The MIT License (MIT) -Copyright (c) 2015-present, Jon Schlinkert. +Copyright (c) 2015 Josh Junon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -20987,115 +7556,116 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- - -util-deprecate 1.0.2 - MIT -https://github.com/TooTallNate/util-deprecate -Copyright (c) 2014 Nathan Rajlich +--------------------------------------------------------- -(The MIT License) +sqlstring 2.3.1 - MIT +https://github.com/mysqljs/sqlstring#readme -Copyright (c) 2014 Nathan Rajlich +Copyright (c) 2012 Felix Geisendorfer (felix@debuggable.com) and contributors -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -util.promisify 1.0.0 - MIT -https://github.com/ljharb/util.promisify#readme -Copyright (c) 2017 Jordan Harband +--------------------------------------------------------- -MIT License +sshpk 1.16.1 - MIT +https://github.com/arekinath/node-sshpk#readme -Copyright (c) 2017 Jordan Harband +Copyright Joyent, Inc. +Copyright 2015 Joyent, Inc. +Copyright 2016 Joyent, Inc. +Copyright 2017 Joyent, Inc. +Copyright 2018 Joyent, Inc. +Copyright Joyent, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -utils-merge 1.0.1 - MIT -https://github.com/jaredhanson/utils-merge#readme -Copyright (c) 2013-2017 Jared Hanson -Copyright (c) 2013-2017 Jared Hanson < http://jaredhanson.net/ (http://jaredhanson.net/)> +stack-trace 0.0.10 - MIT +https://github.com/felixge/node-stack-trace -The MIT License (MIT) +Copyright (c) 2011 Felix Geisendorfer (felix@debuggable.com) -Copyright (c) 2013-2017 Jared Hanson +Copyright (c) 2011 Felix Geisendörfer (felix@debuggable.com) -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +statuses 1.5.0 - MIT +https://github.com/jshttp/statuses#readme + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2016 Douglas Christopher Wilson +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2016 Douglas Christopher Wilson -uuid 3.3.3 - MIT -https://github.com/kelektiv/node-uuid#readme -Copyright 2011, Sebastian Tschan https://blueimp.net -Copyright (c) 2010-2016 Robert Kieffer and other contributors -Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet The MIT License (MIT) -Copyright (c) 2010-2016 Robert Kieffer and other contributors +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2016 Douglas Christopher Wilson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21104,95 +7674,61 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- - -validator 10.11.0 - MIT -https://github.com/chriso/validator.js -Copyright (c) 2018 Chris O'Hara - -Copyright (c) 2018 Chris O'Hara - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -------------------------------------------------------------------- - -------------------------------------------------------------------- +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -vary 1.1.2 - MIT -https://github.com/jshttp/vary#readme -Copyright (c) 2014-2017 Douglas Christopher Wilson -(The MIT License) +--------------------------------------------------------- -Copyright (c) 2014-2017 Douglas Christopher Wilson +--------------------------------------------------------- -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +string_decoder 1.1.1 - MIT +https://github.com/nodejs/string_decoder -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Copyright Joyent, Inc. and other Node contributors. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +Node.js is licensed for use as follows: +""" +Copyright Node.js contributors. All rights reserved. -------------------------------------------------------------------- +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -------------------------------------------------------------------- +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -verror 1.10.0 - MIT -https://github.com/davepacheco/node-verror -Copyright (c) 2016, Joyent, Inc. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" -Copyright (c) 2016, Joyent, Inc. All rights reserved. +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -21202,60 +7738,45 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE - +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" -------------------------------------------------------------------- -------------------------------------------------------------------- -vsce 1.66.0 - MIT -https://code.visualstudio.com -Copyright (c) 2015 Microsoft -Copyright (c) 2014 Josh Wolfe -Copyright (c) 2014 KARASZI Istvan -Copyright (c) Microsoft Corporation -Copyright (c) Isaac Z. Schlueter and Contributors -Copyright (c) 2010 Benjamin Thomas, Robert Kieffer -Copyright (c) 2011 TJ Holowaychuk -Copyright 2012-2015 The Dojo Foundation -copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +--------------------------------------------------------- +--------------------------------------------------------- -Copyright (c) Microsoft Corporation +supports-color 5.5.0 - MIT +https://github.com/chalk/supports-color#readme -All rights reserved. +Copyright (c) Sindre Sorhus (sindresorhus.com) MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following conditions: +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -winston 3.2.1 - MIT -https://github.com/winstonjs/winston#readme -(c) 2015 Nimrod Becker -(c) 2010 Charlie Robbins -(c) 2016 Charlie Robbins -(c) 2011 Daniel Aristizabal -Copyright (c) 2010 Charlie Robbins +tedious 9.2.1 - MIT +https://github.com/tediousjs/tedious -Copyright (c) 2010 Charlie Robbins +Copyright (c) 2010-2018 Mike D Pilsbury + +The MIT License + +Copyright (c) 2010-2018 Mike D Pilsbury Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21275,17 +7796,19 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -winston-transport 4.3.0 - MIT -https://github.com/winstonjs/winston-transport#readme -Copyright (c) 2015 Charlie Robbins & the contributors. +--------------------------------------------------------- + +text-hex 1.0.0 - MIT +https://github.com/3rd-Eden/text-hex + +Copyright (c) 2014-2015 Arnout Kazemier The MIT License (MIT) -Copyright (c) 2015 Charlie Robbins & the contributors. +Copyright (c) 2014-2015 Arnout Kazemier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21306,97 +7829,116 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +toidentifier 1.0.0 - MIT +https://github.com/component/toidentifier#readme -wkx 0.4.8 - MIT -https://github.com/cschwarz/wkx#readme -Copyright (c) 2013 Christian Schwarz -Copyright Joyent, Inc. and other Node contributors. +Copyright (c) 2016 Douglas Christopher Wilson +Copyright (c) 2016 Douglas Christopher Wilson -The MIT License (MIT) +MIT License -Copyright (c) 2013 Christian Schwarz +Copyright (c) 2016 Douglas Christopher Wilson -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -wrap-ansi 3.0.1 - MIT -https://github.com/chalk/wrap-ansi#readme -Copyright (c) Sindre Sorhus (sindresorhus.com) +toposort-class 1.0.1 - MIT +https://github.com/gustavohenke/toposort#readme -MIT License +Copyright (c) 2015 Gustavo Henke and Aaron Trent -Copyright (c) Sindre Sorhus (sindresorhus.com) +The MIT License (MIT) -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) 2015 Gustavo Henke and Aaron Trent -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -xml2js 0.4.22 - MIT -https://github.com/Leonidas-from-XIV/node-xml2js -Copyright 2010, 2011, 2012, 2013. +--------------------------------------------------------- -Copyright 2010, 2011, 2012, 2013. All rights reserved. +triple-beam 1.3.0 - MIT +https://github.com/winstonjs/triple-beam#readme + +Copyright (c) 2017 +(c) 2010 Charlie Robbins + +MIT License + +Copyright (c) 2017 winstonjs Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -xmlbuilder 11.0.1 - MIT -http://github.com/oozcitak/xmlbuilder-js -Copyright (c) 2013 Ozgur Ozcitak +tunnel 0.0.6 - MIT +https://github.com/koichik/node-tunnel/ + +Copyright (c) 2012 Koichi Kobayashi The MIT License (MIT) -Copyright (c) 2013 Ozgur Ozcitak +Copyright (c) 2012 Koichi Kobayashi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21417,65 +7959,193 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -xpath.js 1.1.0 - MIT -https://github.com/yaronn/xpath.js#readme +type-is 1.6.18 - MIT +https://github.com/jshttp/type-is#readme -MIT License +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson -Copyright (c) +(The MIT License) -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +underscore 1.8.3 - MIT +http://underscorejs.org/ + +Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +(c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors Underscore + +Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative +Reporters & Editors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +unpipe 1.0.0 - MIT +https://github.com/stream-utils/unpipe + +Copyright (c) 2015 Douglas Christopher Wilson +Copyright (c) 2015 Douglas Christopher Wilson + +(The MIT License) + +Copyright (c) 2015 Douglas Christopher Wilson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +util-deprecate 1.0.2 - MIT +https://github.com/TooTallNate/util-deprecate + +Copyright (c) 2014 Nathan Rajlich + +(The MIT License) + +Copyright (c) 2014 Nathan Rajlich + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +utils-merge 1.0.1 - MIT +https://github.com/jaredhanson/utils-merge#readme -yauzl 2.10.0 - MIT -https://github.com/thejoshwolfe/yauzl -Copyright (c) 2014 Josh Wolfe +Copyright (c) 2013-2017 Jared Hanson +Copyright (c) 2013-2017 Jared Hanson < http://jaredhanson.net/ (http://jaredhanson.net/)> The MIT License (MIT) -Copyright (c) 2014 Josh Wolfe +Copyright (c) 2013-2017 Jared Hanson -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- + +uuid 3.3.3 - MIT +https://github.com/kelektiv/node-uuid#readme -yazl 2.5.1 - MIT -https://github.com/thejoshwolfe/yazl -Copyright (c) 2014 Josh Wolfe +Copyright 2011, Sebastian Tschan https://blueimp.net +Copyright (c) 2010-2016 Robert Kieffer and other contributors +Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet The MIT License (MIT) -Copyright (c) 2014 Josh Wolfe +Copyright (c) 2010-2016 Robert Kieffer and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21496,140 +8166,101 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- - -------------------------------------------------------------------- - -yn 2.0.0 - MIT -https://github.com/sindresorhus/yn#readme -(c) Sindre Sorhus (http://sindresorhus.com) -Copyright (c) Sindre Sorhus (sindresorhus.com) - -The MIT License (MIT) - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +--------------------------------------------------------- -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +--------------------------------------------------------- +uuid 8.3.0 - MIT +https://github.com/uuidjs/uuid#readme -------------------------------------------------------------------- +Copyright 2011, Sebastian Tschan https://blueimp.net +Copyright (c) Paul Johnston 1999 - 2009 Other contributors Greg Holt, Andrew Kepert, Ydnar, Lostinet -------------------------------------------------------------------- +The MIT License (MIT) -yup 0.27.0 - MIT -https://github.com/jquense/yup -Copyright (c) 2014 Jason Quense -(c) 2011 Colin Snover +Copyright (c) 2010-2020 Robert Kieffer and other contributors -The MIT License (MIT) +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -Copyright (c) 2014 Jason Quense +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +validator 10.11.0 - MIT +https://github.com/chriso/validator.js -tweetnacl 0.14.5 - Unlicense -https://tweetnacl.js.org +Copyright (c) 2018 Chris O'Hara -This is free and unencumbered software released into the public domain. +Copyright (c) 2018 Chris O'Hara -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to - +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -json-schema 0.2.3 - AFL-2.1 OR BSD-3-Clause -https://github.com/kriszyp/json-schema#readme -Copyright (c) 2007 Kris Zyp SitePen (www.sitepen.com) +--------------------------------------------------------- -AFL-2.1 OR BSD-3-Clause +vary 1.1.2 - MIT +https://github.com/jshttp/vary#readme -------------------------------------------------------------------- +Copyright (c) 2014-2017 Douglas Christopher Wilson -------------------------------------------------------------------- +(The MIT License) -regenerator-transform 0.10.1 - BSD-2-Clause AND OTHER -Copyright (c) 2014, Facebook, Inc. +Copyright (c) 2014-2017 Douglas Christopher Wilson -BSD-2-Clause AND OTHER +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -------------------------------------------------------------------- +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. -------------------------------------------------------------------- +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -atob 2.1.2 - MIT OR Apache-2.0 -https://git.coolaj86.com/coolaj86/atob.js.git -Copyright 2015 AJ ONeal -Copyright (c) 2015 AJ ONeal -copyright 2012-2018 AJ ONeal -At your option you may choose either of the following licenses: +--------------------------------------------------------- - * The MIT License (MIT) - * The Apache License 2.0 (Apache-2.0) +--------------------------------------------------------- +verror 1.10.0 - MIT +https://github.com/davepacheco/node-verror -The MIT License (MIT) +Copyright (c) 2016, Joyent, Inc. -Copyright (c) 2015 AJ ONeal +Copyright (c) 2016, Joyent, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21638,276 +8269,158 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and +--------------------------------------------------------- - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and +--------------------------------------------------------- - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. +winston 3.2.1 - MIT +https://github.com/winstonjs/winston#readme - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. +(c) 2015 Nimrod Becker +(c) 2010 Charlie Robbins +(c) 2016 Charlie Robbins +(c) 2011 Daniel Aristizabal +Copyright (c) 2010 Charlie Robbins - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. +Copyright (c) 2010 Charlie Robbins - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. +--------------------------------------------------------- - END OF TERMS AND CONDITIONS +--------------------------------------------------------- - APPENDIX: How to apply the Apache License to your work. +winston-transport 4.3.0 - MIT +https://github.com/winstonjs/winston-transport#readme - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. +Copyright (c) 2015 Charlie Robbins & the contributors. - Copyright 2015 AJ ONeal +The MIT License (MIT) - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +Copyright (c) 2015 Charlie Robbins & the contributors. - http://www.apache.org/licenses/LICENSE-2.0 +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -------------------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -xmldom 0.2.1 - MIT OR LGPL-2.0-only -https://github.com/xmldom/xmldom +--------------------------------------------------------- + +wkx 0.5.0 - MIT +https://github.com/cschwarz/wkx#readme + +Copyright (c) 2013 Christian Schwarz +Copyright Joyent, Inc. and other Node contributors. + +The MIT License (MIT) -You can choose any one of those: +Copyright (c) 2013 Christian Schwarz -The MIT License (MIT): +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: -link:http://opensource.org/licenses/MIT +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -LGPL: -http://www.gnu.org/licenses/lgpl.html +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------- +--------------------------------------------------------- -------------------------------------------------------------------- +--------------------------------------------------------- -path-is-inside 1.0.2 - WTFPL OR MIT -https://github.com/domenic/path-is-inside#readme -Copyright (c) 2004 Sam Hocevar -Copyright (c) 2013-2016 Domenic Denicola +xml2js 0.4.23 - MIT +https://github.com/Leonidas-from-XIV/node-xml2js -Dual licensed under WTFPL and MIT: +Copyright 2010, 2011, 2012, 2013. ---- +Copyright 2010, 2011, 2012, 2013. All rights reserved. -Copyright © 2013–2016 Domenic Denicola +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -This work is free. You can redistribute it and/or modify it under the -terms of the Do What The Fuck You Want To Public License, Version 2, -as published by Sam Hocevar. See below for more details. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. - Copyright (C) 2004 Sam Hocevar - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. +--------------------------------------------------------- - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +--------------------------------------------------------- - 0. You just DO WHAT THE FUCK YOU WANT TO. +xmlbuilder 11.0.1 - MIT +http://github.com/oozcitak/xmlbuilder-js ---- +Copyright (c) 2013 Ozgur Ozcitak The MIT License (MIT) -Copyright © 2013–2016 Domenic Denicola +Copyright (c) 2013 Ozgur Ozcitak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21916,16 +8429,81 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +--------------------------------------------------------- + +--------------------------------------------------------- + +xpath.js 1.1.0 - MIT +https://github.com/yaronn/xpath.js#readme + + +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------- + +--------------------------------------------------------- + +uri-templates 0.2.0 - OTHER + + +Copyright 2011-2012 +Copyright (c) 2011 TJ Holowaychuk + +OTHER + +--------------------------------------------------------- + +--------------------------------------------------------- + +tweetnacl 0.14.5 - Unlicense +https://tweetnacl.js.org/ + + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + +--------------------------------------------------------- --------------------------------------------------------------------