From 7e34f1a2202043b831e95f0573d58544b6295478 Mon Sep 17 00:00:00 2001 From: Yan Zhang <2351748+Eskibear@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:01:16 +0800 Subject: [PATCH 01/16] up version to 1.0.0-preview.1 (#20) --- package-lock.json | 4 ++-- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 71d02854..6a3be0c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview", + "version": "1.0.0-preview.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview", + "version": "1.0.0-preview.1", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.4.1", diff --git a/package.json b/package.json index 148f1718..14bb4489 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview", + "version": "1.0.0-preview.1", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index 6da52662..9628b7f3 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const Version = "1.0.0-preview"; \ No newline at end of file +export const Version = "1.0.0-preview.1"; \ No newline at end of file From 36a89ad44e4ee289a893e56e743232d477d60b23 Mon Sep 17 00:00:00 2001 From: Yan Zhang <2351748+Eskibear@users.noreply.github.com> Date: Thu, 14 Dec 2023 09:23:28 +0800 Subject: [PATCH 02/16] Update version to 1.0.0-preview.2 (#34) --- package-lock.json | 4 ++-- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index fa9cf168..bdda3901 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.1", + "version": "1.0.0-preview.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.1", + "version": "1.0.0-preview.2", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.5.0", diff --git a/package.json b/package.json index 82bea1cc..055b1cc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.1", + "version": "1.0.0-preview.2", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index 9628b7f3..018366e2 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const Version = "1.0.0-preview.1"; \ No newline at end of file +export const Version = "1.0.0-preview.2"; \ No newline at end of file From a034dc9683c92960e49911086a8f2ca8057f764c Mon Sep 17 00:00:00 2001 From: Yan Zhang <2351748+Eskibear@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:11:33 +0800 Subject: [PATCH 03/16] Update version to 1.0.0-preview.3 (#51) --- package-lock.json | 4 ++-- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index eb0af5ed..8972f89e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.2", + "version": "1.0.0-preview.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.2", + "version": "1.0.0-preview.3", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.5.0", diff --git a/package.json b/package.json index ce0804e4..2bcf987b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.2", + "version": "1.0.0-preview.3", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index 018366e2..fadd2b17 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const Version = "1.0.0-preview.2"; \ No newline at end of file +export const Version = "1.0.0-preview.3"; \ No newline at end of file From 5522a85bf8a9d17a4ed9bd9657c72e61c5678675 Mon Sep 17 00:00:00 2001 From: Yan Zhang <2351748+Eskibear@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:05:59 +0800 Subject: [PATCH 04/16] Update version to 1.0.0-preview.4 (#58) --- package-lock.json | 4 ++-- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8972f89e..c886f695 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.3", + "version": "1.0.0-preview.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.3", + "version": "1.0.0-preview.4", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.5.0", diff --git a/package.json b/package.json index 2bcf987b..1d473642 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.3", + "version": "1.0.0-preview.4", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index fadd2b17..ce972f30 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const Version = "1.0.0-preview.3"; \ No newline at end of file +export const Version = "1.0.0-preview.4"; \ No newline at end of file From 11e446ef656e0d374c793c84afa6111e8288f24b Mon Sep 17 00:00:00 2001 From: Yan Zhang <2351748+Eskibear@users.noreply.github.com> Date: Wed, 29 May 2024 22:21:45 +0800 Subject: [PATCH 05/16] Update version to 1.0.0 (#66) --- package-lock.json | 4 ++-- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index c886f695..0f3e4002 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.4", + "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.4", + "version": "1.0.0", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.5.0", diff --git a/package.json b/package.json index 1d473642..f6ce8557 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0-preview.4", + "version": "1.0.0", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index ce972f30..8414a481 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const Version = "1.0.0-preview.4"; \ No newline at end of file +export const Version = "1.0.0"; \ No newline at end of file From e0e584362fcb1ee817bf7b4055c8a361c8bf5103 Mon Sep 17 00:00:00 2001 From: Yan Zhang <2351748+Eskibear@users.noreply.github.com> Date: Fri, 26 Jul 2024 10:53:24 +0800 Subject: [PATCH 06/16] Update version to 1.0.1 (#84) --- package-lock.json | 4 ++-- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1fdad47..e01eeda4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@azure/app-configuration-provider", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "dependencies": { "@azure/app-configuration": "^1.6.0", diff --git a/package.json b/package.json index fda46b44..e6b2c682 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.0.0", + "version": "1.0.1", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index bdd05872..9d62b3b1 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "1.0.0"; \ No newline at end of file +export const VERSION = "1.0.1"; \ No newline at end of file From f2ddbb3573e7c23d0e2a7bba841c8681d84199cc Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:27:52 +0800 Subject: [PATCH 07/16] resolve conflict * update linting rule * fix format issue * update --- .eslintrc | 18 +++++++++++++++++- src/AzureAppConfigurationImpl.ts | 2 +- src/AzureAppConfigurationOptions.ts | 2 +- src/IKeyValueAdapter.ts | 2 +- src/JsonKeyValueAdapter.ts | 2 +- src/RefreshOptions.ts | 2 +- src/WatchedSetting.ts | 2 +- src/common/disposable.ts | 2 +- src/featureManagement/FeatureFlagOptions.ts | 2 +- src/featureManagement/constants.ts | 2 +- src/keyvault/AzureKeyVaultKeyValueAdapter.ts | 2 +- src/keyvault/KeyVaultOptions.ts | 2 +- test/exportedApi.ts | 2 +- test/keyvault.test.ts | 2 +- test/refresh.test.ts | 2 +- test/requestTracing.test.ts | 2 +- test/utils/testHelper.ts | 2 +- 17 files changed, 33 insertions(+), 17 deletions(-) diff --git a/.eslintrc b/.eslintrc index 8b96047e..f2852f86 100644 --- a/.eslintrc +++ b/.eslintrc @@ -40,6 +40,22 @@ "avoidEscape": true } ], - "@typescript-eslint/no-explicit-any": "off" + "@typescript-eslint/no-explicit-any": "off", + "eol-last": [ + "error", + "always" + ], + "no-trailing-spaces": "error", + "space-before-blocks": [ + "error", + "always" + ], + "no-multi-spaces": "error", + "no-multiple-empty-lines": [ + "error", + { + "max": 1 + } + ] } } \ No newline at end of file diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index 6c650244..76d2c963 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -575,4 +575,4 @@ function getValidFeatureFlagSelectors(selectors?: SettingSelector[]): SettingSel } else { return getValidSelectors(selectors); } -} \ No newline at end of file +} diff --git a/src/AzureAppConfigurationOptions.ts b/src/AzureAppConfigurationOptions.ts index e780fc89..c98de463 100644 --- a/src/AzureAppConfigurationOptions.ts +++ b/src/AzureAppConfigurationOptions.ts @@ -47,4 +47,4 @@ export interface AzureAppConfigurationOptions { * Specifies options used to configure feature flags. */ featureFlagOptions?: FeatureFlagOptions; -} \ No newline at end of file +} diff --git a/src/IKeyValueAdapter.ts b/src/IKeyValueAdapter.ts index 530c870b..afd7bdc3 100644 --- a/src/IKeyValueAdapter.ts +++ b/src/IKeyValueAdapter.ts @@ -13,4 +13,4 @@ export interface IKeyValueAdapter { * This method process the original configuration setting, and returns processed key and value in an array. */ processKeyValue(setting: ConfigurationSetting): Promise<[string, unknown]>; -} \ No newline at end of file +} diff --git a/src/JsonKeyValueAdapter.ts b/src/JsonKeyValueAdapter.ts index e821af70..c558f4e4 100644 --- a/src/JsonKeyValueAdapter.ts +++ b/src/JsonKeyValueAdapter.ts @@ -54,4 +54,4 @@ function isJsonContentType(contentTypeValue: string): boolean { } return typeParts[1].split("+").includes("json"); -} \ No newline at end of file +} diff --git a/src/RefreshOptions.ts b/src/RefreshOptions.ts index 0d7b75c3..29f35be2 100644 --- a/src/RefreshOptions.ts +++ b/src/RefreshOptions.ts @@ -20,7 +20,7 @@ export interface RefreshOptions { refreshIntervalInMs?: number; /** - * One or more configuration settings to be watched for changes on the server. + * One or more configuration settings to be watched for changes on the server. * Any modifications to watched settings will refresh all settings loaded by the configuration provider when refresh() is called. */ watchedSettings?: WatchedSetting[]; diff --git a/src/WatchedSetting.ts b/src/WatchedSetting.ts index b714f2ef..40f4d4fb 100644 --- a/src/WatchedSetting.ts +++ b/src/WatchedSetting.ts @@ -15,4 +15,4 @@ export interface WatchedSetting { * Leaving this undefined means this setting does not have a label. */ label?: string; -} \ No newline at end of file +} diff --git a/src/common/disposable.ts b/src/common/disposable.ts index 4843e121..c075b6b1 100644 --- a/src/common/disposable.ts +++ b/src/common/disposable.ts @@ -15,4 +15,4 @@ export class Disposable { } this.#disposed = true; } -} \ No newline at end of file +} diff --git a/src/featureManagement/FeatureFlagOptions.ts b/src/featureManagement/FeatureFlagOptions.ts index de0ff896..6facb592 100644 --- a/src/featureManagement/FeatureFlagOptions.ts +++ b/src/featureManagement/FeatureFlagOptions.ts @@ -27,4 +27,4 @@ export interface FeatureFlagOptions { * Specifies how feature flag refresh is configured. All selected feature flags will be watched for changes. */ refresh?: FeatureFlagRefreshOptions; -} \ No newline at end of file +} diff --git a/src/featureManagement/constants.ts b/src/featureManagement/constants.ts index d8a6afc6..f0082f48 100644 --- a/src/featureManagement/constants.ts +++ b/src/featureManagement/constants.ts @@ -2,4 +2,4 @@ // Licensed under the MIT license. export const FEATURE_MANAGEMENT_KEY_NAME = "feature_management"; -export const FEATURE_FLAGS_KEY_NAME = "feature_flags"; \ No newline at end of file +export const FEATURE_FLAGS_KEY_NAME = "feature_flags"; diff --git a/src/keyvault/AzureKeyVaultKeyValueAdapter.ts b/src/keyvault/AzureKeyVaultKeyValueAdapter.ts index b65a0314..92f6e261 100644 --- a/src/keyvault/AzureKeyVaultKeyValueAdapter.ts +++ b/src/keyvault/AzureKeyVaultKeyValueAdapter.ts @@ -72,4 +72,4 @@ export class AzureKeyVaultKeyValueAdapter implements IKeyValueAdapter { function getHost(url: string) { return new URL(url).host; -} \ No newline at end of file +} diff --git a/src/keyvault/KeyVaultOptions.ts b/src/keyvault/KeyVaultOptions.ts index 88e86a9c..6d476b54 100644 --- a/src/keyvault/KeyVaultOptions.ts +++ b/src/keyvault/KeyVaultOptions.ts @@ -24,4 +24,4 @@ export interface KeyVaultOptions { * @returns The secret value. */ secretResolver?: (keyVaultReference: URL) => string | Promise; -} \ No newline at end of file +} diff --git a/test/exportedApi.ts b/test/exportedApi.ts index 7e6feba1..c49bc1a3 100644 --- a/test/exportedApi.ts +++ b/test/exportedApi.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export { load } from "../src"; \ No newline at end of file +export { load } from "../src"; diff --git a/test/keyvault.test.ts b/test/keyvault.test.ts index 194517a0..5f70d0a5 100644 --- a/test/keyvault.test.ts +++ b/test/keyvault.test.ts @@ -111,4 +111,4 @@ describe("key vault reference", function () { expect(settings.get("TestKey")).eq("SecretValue"); expect(settings.get("TestKey2")).eq("SecretValue2"); }); -}) \ No newline at end of file +}) diff --git a/test/refresh.test.ts b/test/refresh.test.ts index b756038a..021ac3ba 100644 --- a/test/refresh.test.ts +++ b/test/refresh.test.ts @@ -423,4 +423,4 @@ describe("dynamic refresh feature flags", function () { await settings.refresh(); expect(refreshSuccessfulCount).eq(1); // change in feature flags, because page etags are different. }); -}); \ No newline at end of file +}); diff --git a/test/requestTracing.test.ts b/test/requestTracing.test.ts index cdaa7ca3..5362d004 100644 --- a/test/requestTracing.test.ts +++ b/test/requestTracing.test.ts @@ -345,4 +345,4 @@ describe("request tracing", function () { expect(correlationContext.includes("Host=Web")).eq(false); }); }); -}); \ No newline at end of file +}); diff --git a/test/utils/testHelper.ts b/test/utils/testHelper.ts index 80da36bc..9f0034e7 100644 --- a/test/utils/testHelper.ts +++ b/test/utils/testHelper.ts @@ -210,4 +210,4 @@ export { createMockedFeatureFlag, sleepInMs -} \ No newline at end of file +} From b57cb8a6b2b6338f315f70528f32fe2d58a3231d Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:15:53 +0800 Subject: [PATCH 08/16] Update linting rule to enforce to use semicolon (#91) * enforce to use semicolon * fix lint --- .eslintrc | 3 ++- src/AzureAppConfigurationImpl.ts | 2 +- src/JsonKeyValueAdapter.ts | 2 +- src/load.ts | 2 +- src/requestTracing/utils.ts | 4 ++-- test/clientOptions.test.ts | 10 +++++----- test/featureFlag.test.ts | 3 ++- test/json.test.ts | 4 ++-- test/keyvault.test.ts | 2 +- test/load.test.ts | 3 ++- test/refresh.test.ts | 8 ++++---- test/requestTracing.test.ts | 2 +- test/utils/testHelper.ts | 12 ++++++------ 13 files changed, 30 insertions(+), 27 deletions(-) diff --git a/.eslintrc b/.eslintrc index f2852f86..27a13ccf 100644 --- a/.eslintrc +++ b/.eslintrc @@ -56,6 +56,7 @@ { "max": 1 } - ] + ], + "semi": ["error", "always"] } } \ No newline at end of file diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index 76d2c963..f49cbe3b 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -481,7 +481,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { if (index >= 0) { this.#onRefreshListeners.splice(index, 1); } - } + }; return new Disposable(remove); } diff --git a/src/JsonKeyValueAdapter.ts b/src/JsonKeyValueAdapter.ts index c558f4e4..6b77da5d 100644 --- a/src/JsonKeyValueAdapter.ts +++ b/src/JsonKeyValueAdapter.ts @@ -54,4 +54,4 @@ function isJsonContentType(contentTypeValue: string): boolean { } return typeParts[1].split("+").includes("json"); -} +} diff --git a/src/load.ts b/src/load.ts index d5559c07..10dda11e 100644 --- a/src/load.ts +++ b/src/load.ts @@ -94,7 +94,7 @@ function getClientOptions(options?: AzureAppConfigurationOptions): AppConfigurat const defaultRetryOptions = { maxRetries: MaxRetries, maxRetryDelayInMs: MaxRetryDelayInMs, - } + }; const retryOptions = Object.assign({}, defaultRetryOptions, options?.clientOptions?.retryOptions); return Object.assign({}, options?.clientOptions, { diff --git a/src/requestTracing/utils.ts b/src/requestTracing/utils.ts index 20d19313..f979bf47 100644 --- a/src/requestTracing/utils.ts +++ b/src/requestTracing/utils.ts @@ -40,7 +40,7 @@ export function listConfigurationSettingsWithTrace( customHeaders: { [CORRELATION_CONTEXT_HEADER_NAME]: createCorrelationContextHeader(appConfigOptions, initialLoadCompleted) } - } + }; } return client.listConfigurationSettings(actualListOptions); @@ -64,7 +64,7 @@ export function getConfigurationSettingWithTrace( customHeaders: { [CORRELATION_CONTEXT_HEADER_NAME]: createCorrelationContextHeader(appConfigOptions, initialLoadCompleted) } - } + }; } return client.getConfigurationSetting(configurationSettingId, actualGetOptions); diff --git a/test/clientOptions.test.ts b/test/clientOptions.test.ts index 0b970d93..58bbd353 100644 --- a/test/clientOptions.test.ts +++ b/test/clientOptions.test.ts @@ -37,7 +37,7 @@ describe("custom client options", function () { afterEach(() => { nock.restore(); - }) + }); it("should retry 2 times by default", async () => { const countPolicy = new HttpRequestCountPolicy(); @@ -49,7 +49,7 @@ describe("custom client options", function () { position: "perRetry" }] } - }) + }); }; let error; try { @@ -74,7 +74,7 @@ describe("custom client options", function () { maxRetries } } - }) + }); }; let error; @@ -109,7 +109,7 @@ describe("custom client options", function () { position: "perRetry" }] } - }) + }); }; let error; try { @@ -120,4 +120,4 @@ describe("custom client options", function () { expect(error).not.undefined; expect(countPolicy.count).eq(3); }); -}) +}); diff --git a/test/featureFlag.test.ts b/test/featureFlag.test.ts index 22db36af..5022c0fe 100644 --- a/test/featureFlag.test.ts +++ b/test/featureFlag.test.ts @@ -65,7 +65,8 @@ describe("feature flags", function () { after(() => { restoreMocks(); - }) + }); + it("should load feature flags if enabled", async () => { const connectionString = createMockedConnectionString(); const settings = await load(connectionString, { diff --git a/test/json.test.ts b/test/json.test.ts index 0d7e9484..b25c3392 100644 --- a/test/json.test.ts +++ b/test/json.test.ts @@ -17,7 +17,7 @@ describe("json", function () { afterEach(() => { restoreMocks(); - }) + }); it("should load and parse if content type is application/json", async () => { mockAppConfigurationClientListConfigurationSettings([jsonKeyValue]); @@ -86,4 +86,4 @@ describe("json", function () { expect(settings.get("json.settings.emptyString")).eq("", "is empty string"); expect(settings.get("json.settings.illegalString")).eq("[unclosed", "is illegal string"); }); -}) +}); diff --git a/test/keyvault.test.ts b/test/keyvault.test.ts index 5f70d0a5..eaed0476 100644 --- a/test/keyvault.test.ts +++ b/test/keyvault.test.ts @@ -111,4 +111,4 @@ describe("key vault reference", function () { expect(settings.get("TestKey")).eq("SecretValue"); expect(settings.get("TestKey2")).eq("SecretValue2"); }); -}) +}); diff --git a/test/load.test.ts b/test/load.test.ts index abe7cb3a..2bd0e58d 100644 --- a/test/load.test.ts +++ b/test/load.test.ts @@ -85,7 +85,8 @@ describe("load", function () { after(() => { restoreMocks(); - }) + }); + it("should load data from config store with connection string", async () => { const connectionString = createMockedConnectionString(); const settings = await load(connectionString); diff --git a/test/refresh.test.ts b/test/refresh.test.ts index 021ac3ba..2af8842e 100644 --- a/test/refresh.test.ts +++ b/test/refresh.test.ts @@ -33,12 +33,12 @@ describe("dynamic refresh", function () { { value: "30", key: "app.settings.fontSize", label: "prod" } ].map(createMockedKeyValue); mockAppConfigurationClientListConfigurationSettings(mockedKVs); - mockAppConfigurationClientGetConfigurationSetting(mockedKVs) + mockAppConfigurationClientGetConfigurationSetting(mockedKVs); }); afterEach(() => { restoreMocks(); - }) + }); it("should throw error when refresh is not enabled but refresh is called", async () => { const connectionString = createMockedConnectionString(); @@ -331,14 +331,14 @@ describe("dynamic refresh feature flags", function () { afterEach(() => { restoreMocks(); - }) + }); it("should refresh feature flags when enabled", async () => { mockedKVs = [ createMockedFeatureFlag("Beta", { enabled: true }) ]; mockAppConfigurationClientListConfigurationSettings(mockedKVs); - mockAppConfigurationClientGetConfigurationSetting(mockedKVs) + mockAppConfigurationClientGetConfigurationSetting(mockedKVs); const connectionString = createMockedConnectionString(); const settings = await load(connectionString, { diff --git a/test/requestTracing.test.ts b/test/requestTracing.test.ts index 5362d004..fbf5cccb 100644 --- a/test/requestTracing.test.ts +++ b/test/requestTracing.test.ts @@ -42,7 +42,7 @@ describe("request tracing", function () { }); after(() => { - }) + }); it("should have correct user agent prefix", async () => { try { diff --git a/test/utils/testHelper.ts b/test/utils/testHelper.ts index 9f0034e7..6e787dd7 100644 --- a/test/utils/testHelper.ts +++ b/test/utils/testHelper.ts @@ -35,7 +35,7 @@ function _filterKVs(unfilteredKvs: ConfigurationSetting[], listOptions: any) { labelMatched = kv.label === labelFilter; } return keyMatched && labelMatched; - }) + }); } /** @@ -86,7 +86,7 @@ function mockAppConfigurationClientListConfigurationSettings(...pages: Configura }); } } - } + }; } }; @@ -126,7 +126,7 @@ function mockSecretClientGetSecret(uriValueList: [string, string][]) { name: secretName, value: dict.get(url.toString()) } as KeyVaultSecret; - }) + }); } function restoreMocks() { @@ -139,11 +139,11 @@ const createMockedConnectionString = (endpoint = createMockedEndpoint(), secret const toEncodeAsBytes = Buffer.from(secret); const returnValue = toEncodeAsBytes.toString("base64"); return `Endpoint=${endpoint};Id=${id};Secret=${returnValue}`; -} +}; const createMockedTokenCredential = (tenantId = TEST_TENANT_ID, clientId = TEST_CLIENT_ID, clientSecret = TEST_CLIENT_SECRET) => { return new ClientSecretCredential(tenantId, clientId, clientSecret); -} +}; const createMockedKeyVaultReference = (key: string, vaultUri: string): ConfigurationSetting => ({ // https://${vaultName}.vault.azure.net/secrets/${secretName} @@ -210,4 +210,4 @@ export { createMockedFeatureFlag, sleepInMs -} +}; From 7e9a3126bc85b4c255b11bfd3a919982ac564bad Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Fri, 13 Sep 2024 15:36:35 +0800 Subject: [PATCH 09/16] use isRestError API (#94) --- rollup.config.mjs | 2 +- src/AzureAppConfigurationImpl.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rollup.config.mjs b/rollup.config.mjs index c16ce3d7..b2e87c64 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -4,7 +4,7 @@ import dts from "rollup-plugin-dts"; export default [ { - external: ["@azure/app-configuration", "@azure/keyvault-secrets"], + external: ["@azure/app-configuration", "@azure/keyvault-secrets", "@azure/core-rest-pipeline"], input: "src/index.ts", output: [ { diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index f49cbe3b..30eba149 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import { AppConfigurationClient, ConfigurationSetting, ConfigurationSettingId, GetConfigurationSettingOptions, GetConfigurationSettingResponse, ListConfigurationSettingsOptions, featureFlagPrefix, isFeatureFlag } from "@azure/app-configuration"; -import { RestError } from "@azure/core-rest-pipeline"; +import { isRestError } from "@azure/core-rest-pipeline"; import { AzureAppConfiguration, ConfigurationObjectConstructionOptions } from "./AzureAppConfiguration"; import { AzureAppConfigurationOptions } from "./AzureAppConfigurationOptions"; import { IKeyValueAdapter } from "./IKeyValueAdapter"; @@ -524,7 +524,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { customOptions ); } catch (error) { - if (error instanceof RestError && error.statusCode === 404) { + if (isRestError(error) && error.statusCode === 404) { response = undefined; } else { throw error; @@ -575,4 +575,4 @@ function getValidFeatureFlagSelectors(selectors?: SettingSelector[]): SettingSel } else { return getValidSelectors(selectors); } -} +} From e9db70a07ca423443cb9589f2f8260cda88660de Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Sat, 14 Sep 2024 11:14:10 +0800 Subject: [PATCH 10/16] Make testsuite compatible with node 22.x (#96) * work around with global navigator in node 22 * fix lint --- .github/workflows/ci.yml | 2 +- test/requestTracing.test.ts | 34 +++++++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81490d40..c4b9e1af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: [18.x, 20.x] + node-version: [18.x, 20.x, 22.x] steps: - uses: actions/checkout@v3 diff --git a/test/requestTracing.test.ts b/test/requestTracing.test.ts index fbf5cccb..1496b097 100644 --- a/test/requestTracing.test.ts +++ b/test/requestTracing.test.ts @@ -166,7 +166,12 @@ describe("request tracing", function () { afterEach(() => { // Restore the original values after each test - (global as any).navigator = originalNavigator; + // global.navigator was added in node 21, https://nodejs.org/api/globals.html#navigator_1 + // global.navigator only has a getter, so we have to use Object.defineProperty to modify it + Object.defineProperty(global, "navigator", { + value: originalNavigator, + configurable: true + }); (global as any).WorkerNavigator = originalWorkerNavigator; (global as any).WorkerGlobalScope = originalWorkerGlobalScope; (global as any).importScripts = originalImportScripts; @@ -174,7 +179,10 @@ describe("request tracing", function () { it("should identify WebWorker environment", async () => { (global as any).WorkerNavigator = function WorkerNavigator() { }; - (global as any).navigator = new (global as any).WorkerNavigator(); + Object.defineProperty(global, "navigator", { + value: new (global as any).WorkerNavigator(), + configurable: true + }); (global as any).WorkerGlobalScope = function WorkerGlobalScope() { }; (global as any).importScripts = function importScripts() { }; @@ -188,7 +196,10 @@ describe("request tracing", function () { }); it("is not WebWorker when WorkerNavigator is undefined", async () => { - (global as any).navigator = { userAgent: "node.js" } as any; // Mock navigator + Object.defineProperty(global, "navigator", { + value: { userAgent: "node.js" } as any, // Mock navigator + configurable: true + }); (global as any).WorkerNavigator = undefined; (global as any).WorkerGlobalScope = function WorkerGlobalScope() { }; (global as any).importScripts = function importScripts() { }; @@ -203,7 +214,10 @@ describe("request tracing", function () { }); it("is not WebWorker when navigator is not an instance of WorkerNavigator", async () => { - (global as any).navigator = { userAgent: "node.js" } as any; // Mock navigator but not an instance of WorkerNavigator + Object.defineProperty(global, "navigator", { + value: { userAgent: "node.js" } as any, // Mock navigator but not an instance of WorkerNavigator + configurable: true + }); (global as any).WorkerNavigator = function WorkerNavigator() { }; (global as any).WorkerGlobalScope = function WorkerGlobalScope() { }; (global as any).importScripts = function importScripts() { }; @@ -219,7 +233,10 @@ describe("request tracing", function () { it("is not WebWorker when WorkerGlobalScope is undefined", async () => { (global as any).WorkerNavigator = function WorkerNavigator() { }; - (global as any).navigator = new (global as any).WorkerNavigator(); + Object.defineProperty(global, "navigator", { + value: new (global as any).WorkerNavigator(), + configurable: true + }); (global as any).WorkerGlobalScope = undefined; (global as any).importScripts = function importScripts() { }; @@ -234,7 +251,10 @@ describe("request tracing", function () { it("is not WebWorker when importScripts is undefined", async () => { (global as any).WorkerNavigator = function WorkerNavigator() { }; - (global as any).navigator = new (global as any).WorkerNavigator(); + Object.defineProperty(global, "navigator", { + value: new (global as any).WorkerNavigator(), + configurable: true + }); (global as any).WorkerGlobalScope = function WorkerGlobalScope() { }; (global as any).importScripts = undefined; @@ -345,4 +365,4 @@ describe("request tracing", function () { expect(correlationContext.includes("Host=Web")).eq(false); }); }); -}); +}); From 39cebdb4e8175ac44596f61eaccdb85dc711e3e0 Mon Sep 17 00:00:00 2001 From: Ross Grambo Date: Mon, 30 Sep 2024 10:55:58 -0700 Subject: [PATCH 11/16] Adds additional undefined check (#104) --- src/requestTracing/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/requestTracing/utils.ts b/src/requestTracing/utils.ts index f979bf47..0d851a61 100644 --- a/src/requestTracing/utils.ts +++ b/src/requestTracing/utils.ts @@ -111,7 +111,7 @@ export function requestTracingEnabled(): boolean { function getEnvironmentVariable(name: string) { // Make it compatible with non-Node.js runtime - if (typeof process?.env === "object") { + if (typeof process !== "undefined" && typeof process?.env === "object") { return process.env[name]; } else { return undefined; From 0d6f99c7f3c897753d64af2f5e36e3b08b3e95bb Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:40:33 +0800 Subject: [PATCH 12/16] add js file extension to imports (#109) --- src/AzureAppConfiguration.ts | 2 +- src/AzureAppConfigurationImpl.ts | 22 ++++++++++---------- src/AzureAppConfigurationOptions.ts | 10 ++++----- src/JsonKeyValueAdapter.ts | 2 +- src/RefreshOptions.ts | 2 +- src/featureManagement/FeatureFlagOptions.ts | 6 +++--- src/index.ts | 9 ++++---- src/keyvault/AzureKeyVaultKeyValueAdapter.ts | 6 +++--- src/load.ts | 8 +++---- src/requestTracing/constants.ts | 2 +- src/requestTracing/utils.ts | 2 +- test/clientOptions.test.ts | 4 ++-- test/featureFlag.test.ts | 4 ++-- test/json.test.ts | 4 ++-- test/keyvault.test.ts | 6 +++--- test/load.test.ts | 4 ++-- test/refresh.test.ts | 6 +++--- test/requestTracing.test.ts | 4 ++-- 18 files changed, 52 insertions(+), 51 deletions(-) diff --git a/src/AzureAppConfiguration.ts b/src/AzureAppConfiguration.ts index 7d8120d3..3f2918be 100644 --- a/src/AzureAppConfiguration.ts +++ b/src/AzureAppConfiguration.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { Disposable } from "./common/disposable"; +import { Disposable } from "./common/disposable.js"; export type AzureAppConfiguration = { /** diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index 30eba149..4a0acc04 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -3,17 +3,17 @@ import { AppConfigurationClient, ConfigurationSetting, ConfigurationSettingId, GetConfigurationSettingOptions, GetConfigurationSettingResponse, ListConfigurationSettingsOptions, featureFlagPrefix, isFeatureFlag } from "@azure/app-configuration"; import { isRestError } from "@azure/core-rest-pipeline"; -import { AzureAppConfiguration, ConfigurationObjectConstructionOptions } from "./AzureAppConfiguration"; -import { AzureAppConfigurationOptions } from "./AzureAppConfigurationOptions"; -import { IKeyValueAdapter } from "./IKeyValueAdapter"; -import { JsonKeyValueAdapter } from "./JsonKeyValueAdapter"; -import { DEFAULT_REFRESH_INTERVAL_IN_MS, MIN_REFRESH_INTERVAL_IN_MS } from "./RefreshOptions"; -import { Disposable } from "./common/disposable"; -import { FEATURE_FLAGS_KEY_NAME, FEATURE_MANAGEMENT_KEY_NAME } from "./featureManagement/constants"; -import { AzureKeyVaultKeyValueAdapter } from "./keyvault/AzureKeyVaultKeyValueAdapter"; -import { RefreshTimer } from "./refresh/RefreshTimer"; -import { getConfigurationSettingWithTrace, listConfigurationSettingsWithTrace, requestTracingEnabled } from "./requestTracing/utils"; -import { KeyFilter, LabelFilter, SettingSelector } from "./types"; +import { AzureAppConfiguration, ConfigurationObjectConstructionOptions } from "./AzureAppConfiguration.js"; +import { AzureAppConfigurationOptions } from "./AzureAppConfigurationOptions.js"; +import { IKeyValueAdapter } from "./IKeyValueAdapter.js"; +import { JsonKeyValueAdapter } from "./JsonKeyValueAdapter.js"; +import { DEFAULT_REFRESH_INTERVAL_IN_MS, MIN_REFRESH_INTERVAL_IN_MS } from "./RefreshOptions.js"; +import { Disposable } from "./common/disposable.js"; +import { FEATURE_FLAGS_KEY_NAME, FEATURE_MANAGEMENT_KEY_NAME } from "./featureManagement/constants.js"; +import { AzureKeyVaultKeyValueAdapter } from "./keyvault/AzureKeyVaultKeyValueAdapter.js"; +import { RefreshTimer } from "./refresh/RefreshTimer.js"; +import { getConfigurationSettingWithTrace, listConfigurationSettingsWithTrace, requestTracingEnabled } from "./requestTracing/utils.js"; +import { KeyFilter, LabelFilter, SettingSelector } from "./types.js"; type PagedSettingSelector = SettingSelector & { /** diff --git a/src/AzureAppConfigurationOptions.ts b/src/AzureAppConfigurationOptions.ts index c98de463..f88ad67c 100644 --- a/src/AzureAppConfigurationOptions.ts +++ b/src/AzureAppConfigurationOptions.ts @@ -2,10 +2,10 @@ // Licensed under the MIT license. import { AppConfigurationClientOptions } from "@azure/app-configuration"; -import { KeyVaultOptions } from "./keyvault/KeyVaultOptions"; -import { RefreshOptions } from "./RefreshOptions"; -import { SettingSelector } from "./types"; -import { FeatureFlagOptions } from "./featureManagement/FeatureFlagOptions"; +import { KeyVaultOptions } from "./keyvault/KeyVaultOptions.js"; +import { RefreshOptions } from "./RefreshOptions.js"; +import { SettingSelector } from "./types.js"; +import { FeatureFlagOptions } from "./featureManagement/FeatureFlagOptions.js"; export const MaxRetries = 2; export const MaxRetryDelayInMs = 60000; @@ -47,4 +47,4 @@ export interface AzureAppConfigurationOptions { * Specifies options used to configure feature flags. */ featureFlagOptions?: FeatureFlagOptions; -} +} diff --git a/src/JsonKeyValueAdapter.ts b/src/JsonKeyValueAdapter.ts index 6b77da5d..d9157a45 100644 --- a/src/JsonKeyValueAdapter.ts +++ b/src/JsonKeyValueAdapter.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import { ConfigurationSetting, featureFlagContentType, secretReferenceContentType } from "@azure/app-configuration"; -import { IKeyValueAdapter } from "./IKeyValueAdapter"; +import { IKeyValueAdapter } from "./IKeyValueAdapter.js"; export class JsonKeyValueAdapter implements IKeyValueAdapter { static readonly #ExcludedJsonContentTypes: string[] = [ diff --git a/src/RefreshOptions.ts b/src/RefreshOptions.ts index 29f35be2..37425112 100644 --- a/src/RefreshOptions.ts +++ b/src/RefreshOptions.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { WatchedSetting } from "./WatchedSetting"; +import { WatchedSetting } from "./WatchedSetting.js"; export const DEFAULT_REFRESH_INTERVAL_IN_MS = 30 * 1000; export const MIN_REFRESH_INTERVAL_IN_MS = 1 * 1000; diff --git a/src/featureManagement/FeatureFlagOptions.ts b/src/featureManagement/FeatureFlagOptions.ts index 6facb592..eedf9ec7 100644 --- a/src/featureManagement/FeatureFlagOptions.ts +++ b/src/featureManagement/FeatureFlagOptions.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { FeatureFlagRefreshOptions } from "../RefreshOptions"; -import { SettingSelector } from "../types"; +import { FeatureFlagRefreshOptions } from "../RefreshOptions.js"; +import { SettingSelector } from "../types.js"; /** * Options used to configure feature flags. @@ -27,4 +27,4 @@ export interface FeatureFlagOptions { * Specifies how feature flag refresh is configured. All selected feature flags will be watched for changes. */ refresh?: FeatureFlagRefreshOptions; -} +} diff --git a/src/index.ts b/src/index.ts index dd246046..1a3bb318 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export { AzureAppConfiguration } from "./AzureAppConfiguration"; -export { Disposable } from "./common/disposable"; -export { load } from "./load"; -export { KeyFilter, LabelFilter } from "./types"; +export { AzureAppConfiguration } from "./AzureAppConfiguration.js"; +export { Disposable } from "./common/disposable.js"; +export { load } from "./load.js"; +export { KeyFilter, LabelFilter } from "./types.js"; +export { VERSION } from "./version.js"; diff --git a/src/keyvault/AzureKeyVaultKeyValueAdapter.ts b/src/keyvault/AzureKeyVaultKeyValueAdapter.ts index 92f6e261..1b6fdcc4 100644 --- a/src/keyvault/AzureKeyVaultKeyValueAdapter.ts +++ b/src/keyvault/AzureKeyVaultKeyValueAdapter.ts @@ -2,8 +2,8 @@ // Licensed under the MIT license. import { ConfigurationSetting, isSecretReference, parseSecretReference } from "@azure/app-configuration"; -import { IKeyValueAdapter } from "../IKeyValueAdapter"; -import { KeyVaultOptions } from "./KeyVaultOptions"; +import { IKeyValueAdapter } from "../IKeyValueAdapter.js"; +import { KeyVaultOptions } from "./KeyVaultOptions.js"; import { SecretClient, parseKeyVaultSecretIdentifier } from "@azure/keyvault-secrets"; export class AzureKeyVaultKeyValueAdapter implements IKeyValueAdapter { @@ -72,4 +72,4 @@ export class AzureKeyVaultKeyValueAdapter implements IKeyValueAdapter { function getHost(url: string) { return new URL(url).host; -} +} diff --git a/src/load.ts b/src/load.ts index 10dda11e..cb78f4d3 100644 --- a/src/load.ts +++ b/src/load.ts @@ -3,10 +3,10 @@ import { AppConfigurationClient, AppConfigurationClientOptions } from "@azure/app-configuration"; import { TokenCredential } from "@azure/identity"; -import { AzureAppConfiguration } from "./AzureAppConfiguration"; -import { AzureAppConfigurationImpl } from "./AzureAppConfigurationImpl"; -import { AzureAppConfigurationOptions, MaxRetries, MaxRetryDelayInMs } from "./AzureAppConfigurationOptions"; -import * as RequestTracing from "./requestTracing/constants"; +import { AzureAppConfiguration } from "./AzureAppConfiguration.js"; +import { AzureAppConfigurationImpl } from "./AzureAppConfigurationImpl.js"; +import { AzureAppConfigurationOptions, MaxRetries, MaxRetryDelayInMs } from "./AzureAppConfigurationOptions.js"; +import * as RequestTracing from "./requestTracing/constants.js"; const MIN_DELAY_FOR_UNHANDLED_ERROR: number = 5000; // 5 seconds diff --git a/src/requestTracing/constants.ts b/src/requestTracing/constants.ts index be33aa5d..d46cdfda 100644 --- a/src/requestTracing/constants.ts +++ b/src/requestTracing/constants.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { VERSION } from "../version"; +import { VERSION } from "../version.js"; export const ENV_AZURE_APP_CONFIGURATION_TRACING_DISABLED = "AZURE_APP_CONFIGURATION_TRACING_DISABLED"; diff --git a/src/requestTracing/utils.ts b/src/requestTracing/utils.ts index 0d851a61..de335737 100644 --- a/src/requestTracing/utils.ts +++ b/src/requestTracing/utils.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import { AppConfigurationClient, ConfigurationSettingId, GetConfigurationSettingOptions, ListConfigurationSettingsOptions } from "@azure/app-configuration"; -import { AzureAppConfigurationOptions } from "../AzureAppConfigurationOptions"; +import { AzureAppConfigurationOptions } from "../AzureAppConfigurationOptions.js"; import { AZURE_FUNCTION_ENV_VAR, AZURE_WEB_APP_ENV_VAR, diff --git a/test/clientOptions.test.ts b/test/clientOptions.test.ts index 58bbd353..62e1b21c 100644 --- a/test/clientOptions.test.ts +++ b/test/clientOptions.test.ts @@ -5,8 +5,8 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; -import { load } from "./exportedApi"; -import { createMockedConnectionString } from "./utils/testHelper"; +import { load } from "./exportedApi.js"; +import { createMockedConnectionString } from "./utils/testHelper.js"; import * as nock from "nock"; class HttpRequestCountPolicy { diff --git a/test/featureFlag.test.ts b/test/featureFlag.test.ts index 5022c0fe..1bf8eae2 100644 --- a/test/featureFlag.test.ts +++ b/test/featureFlag.test.ts @@ -3,8 +3,8 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; -import { load } from "./exportedApi"; -import { createMockedConnectionString, createMockedFeatureFlag, createMockedKeyValue, mockAppConfigurationClientListConfigurationSettings, restoreMocks } from "./utils/testHelper"; +import { load } from "./exportedApi.js"; +import { createMockedConnectionString, createMockedFeatureFlag, createMockedKeyValue, mockAppConfigurationClientListConfigurationSettings, restoreMocks } from "./utils/testHelper.js"; chai.use(chaiAsPromised); const expect = chai.expect; diff --git a/test/json.test.ts b/test/json.test.ts index b25c3392..c139d53b 100644 --- a/test/json.test.ts +++ b/test/json.test.ts @@ -5,8 +5,8 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; -import { load } from "./exportedApi"; -import { mockAppConfigurationClientListConfigurationSettings, restoreMocks, createMockedConnectionString, createMockedKeyVaultReference, createMockedJsonKeyValue } from "./utils/testHelper"; +import { load } from "./exportedApi.js"; +import { mockAppConfigurationClientListConfigurationSettings, restoreMocks, createMockedConnectionString, createMockedKeyVaultReference, createMockedJsonKeyValue } from "./utils/testHelper.js"; const jsonKeyValue = createMockedJsonKeyValue("json.settings.logging", '{"Test":{"Level":"Debug"},"Prod":{"Level":"Warning"}}'); const keyVaultKeyValue = createMockedKeyVaultReference("TestKey", "https://fake-vault-name.vault.azure.net/secrets/fakeSecretName"); diff --git a/test/keyvault.test.ts b/test/keyvault.test.ts index eaed0476..cf01235c 100644 --- a/test/keyvault.test.ts +++ b/test/keyvault.test.ts @@ -5,8 +5,8 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; -import { load } from "./exportedApi"; -import { sinon, createMockedConnectionString, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, mockSecretClientGetSecret, restoreMocks, createMockedKeyVaultReference } from "./utils/testHelper"; +import { load } from "./exportedApi.js"; +import { sinon, createMockedConnectionString, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, mockSecretClientGetSecret, restoreMocks, createMockedKeyVaultReference } from "./utils/testHelper.js"; import { KeyVaultSecret, SecretClient } from "@azure/keyvault-secrets"; const mockedData = [ @@ -111,4 +111,4 @@ describe("key vault reference", function () { expect(settings.get("TestKey")).eq("SecretValue"); expect(settings.get("TestKey2")).eq("SecretValue2"); }); -}); +}); diff --git a/test/load.test.ts b/test/load.test.ts index 2bd0e58d..ce22b1a8 100644 --- a/test/load.test.ts +++ b/test/load.test.ts @@ -5,8 +5,8 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; -import { load } from "./exportedApi"; -import { mockAppConfigurationClientListConfigurationSettings, restoreMocks, createMockedConnectionString, createMockedEndpoint, createMockedTokenCredential, createMockedKeyValue } from "./utils/testHelper"; +import { load } from "./exportedApi.js"; +import { mockAppConfigurationClientListConfigurationSettings, restoreMocks, createMockedConnectionString, createMockedEndpoint, createMockedTokenCredential, createMockedKeyValue } from "./utils/testHelper.js"; const mockedKVs = [{ key: "app.settings.fontColor", diff --git a/test/refresh.test.ts b/test/refresh.test.ts index 2af8842e..fcffaee5 100644 --- a/test/refresh.test.ts +++ b/test/refresh.test.ts @@ -5,8 +5,8 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; -import { load } from "./exportedApi"; -import { mockAppConfigurationClientListConfigurationSettings, mockAppConfigurationClientGetConfigurationSetting, restoreMocks, createMockedConnectionString, createMockedKeyValue, sleepInMs, createMockedFeatureFlag } from "./utils/testHelper"; +import { load } from "./exportedApi.js"; +import { mockAppConfigurationClientListConfigurationSettings, mockAppConfigurationClientGetConfigurationSetting, restoreMocks, createMockedConnectionString, createMockedKeyValue, sleepInMs, createMockedFeatureFlag } from "./utils/testHelper.js"; import * as uuid from "uuid"; let mockedKVs: any[] = []; @@ -423,4 +423,4 @@ describe("dynamic refresh feature flags", function () { await settings.refresh(); expect(refreshSuccessfulCount).eq(1); // change in feature flags, because page etags are different. }); -}); +}); diff --git a/test/requestTracing.test.ts b/test/requestTracing.test.ts index 1496b097..d4e7edcf 100644 --- a/test/requestTracing.test.ts +++ b/test/requestTracing.test.ts @@ -5,8 +5,8 @@ import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); const expect = chai.expect; -import { createMockedConnectionString, createMockedKeyValue, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, restoreMocks, sleepInMs } from "./utils/testHelper"; -import { load } from "./exportedApi"; +import { createMockedConnectionString, createMockedKeyValue, createMockedTokenCredential, mockAppConfigurationClientListConfigurationSettings, restoreMocks, sleepInMs } from "./utils/testHelper.js"; +import { load } from "./exportedApi.js"; class HttpRequestHeadersPolicy { headers: any; From af6a3d0d5e1011fa18198cd61edae61db6dd2d03 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Tue, 22 Oct 2024 10:21:51 +0800 Subject: [PATCH 13/16] update typescript version (#112) --- package-lock.json | 2637 +----------------------------- package.json | 6 +- src/AzureAppConfigurationImpl.ts | 8 +- 3 files changed, 31 insertions(+), 2620 deletions(-) diff --git a/package-lock.json b/package-lock.json index b6171131..d36f2b4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "@azure/app-configuration-provider", "version": "1.1.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -16,7 +16,7 @@ "devDependencies": { "@rollup/plugin-typescript": "^11.1.2", "@types/mocha": "^10.0.4", - "@types/node": "^20.5.7", + "@types/node": "^22.7.7", "@types/sinon": "^17.0.1", "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.6.0", @@ -28,11 +28,11 @@ "mocha": "^10.2.0", "nock": "^13.3.3", "rimraf": "^5.0.1", - "rollup": "^3.26.3", + "rollup": "^3.29.5", "rollup-plugin-dts": "^5.3.0", "sinon": "^15.2.0", "tslib": "^2.6.0", - "typescript": "^5.1.6", + "typescript": "^5.6.3", "uuid": "^9.0.1" } }, @@ -865,12 +865,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "22.7.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz", + "integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==", "dev": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~6.19.2" } }, "node_modules/@types/semver": { @@ -2520,12 +2520,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -2865,9 +2865,9 @@ } }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "dev": true, "dependencies": { "isarray": "0.0.1" @@ -3081,9 +3081,9 @@ } }, "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -3421,9 +3421,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -3434,9 +3434,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, "node_modules/uri-js": { @@ -3591,2594 +3591,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true - }, - "@azure/abort-controller": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", - "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", - "requires": { - "tslib": "^2.2.0" - } - }, - "@azure/app-configuration": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@azure/app-configuration/-/app-configuration-1.6.1.tgz", - "integrity": "sha512-pk8zyG/8Nc6VN7uDA9QY19UFhTXneUbnB+5IcW9uuPyVDXU17TcXBI4xY1ZBm7hmhn0yh3CeZK4kOxa/tjsMqQ==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-http-compat": "^2.0.0", - "@azure/core-lro": "^2.5.1", - "@azure/core-paging": "^1.4.0", - "@azure/core-rest-pipeline": "^1.6.0", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.6.1", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - }, - "dependencies": { - "@azure/core-http-compat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.0.1.tgz", - "integrity": "sha512-xpQZz/q7E0jSW4rckrTo2mDFDQgo6I69hBU4voMQi7REi6JRW5a+KfVkbJCFCWnkFmP6cAJ0IbuudTdf/MEBOQ==", - "requires": { - "@azure/abort-controller": "^1.0.4", - "@azure/core-client": "^1.3.0", - "@azure/core-rest-pipeline": "^1.3.0" - } - } - } - }, - "@azure/core-auth": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", - "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.1.0", - "tslib": "^2.2.0" - } - }, - "@azure/core-client": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.3.tgz", - "integrity": "sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-rest-pipeline": "^1.9.1", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - } - }, - "@azure/core-http-compat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-1.3.0.tgz", - "integrity": "sha512-ZN9avruqbQ5TxopzG3ih3KRy52n8OAbitX3fnZT5go4hzu0J+KVPSzkL+Wt3hpJpdG8WIfg1sBD1tWkgUdEpBA==", - "requires": { - "@azure/abort-controller": "^1.0.4", - "@azure/core-client": "^1.3.0", - "@azure/core-rest-pipeline": "^1.3.0" - } - }, - "@azure/core-lro": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", - "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-util": "^1.2.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - } - }, - "@azure/core-paging": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.5.0.tgz", - "integrity": "sha512-zqWdVIt+2Z+3wqxEOGzR5hXFZ8MGKK52x4vFLw8n58pR6ZfKRx3EXYTxTaYxYHc/PexPUTyimcTWFJbji9Z6Iw==", - "requires": { - "tslib": "^2.2.0" - } - }, - "@azure/core-rest-pipeline": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.2.tgz", - "integrity": "sha512-wLLJQdL4v1yoqYtEtjKNjf8pJ/G/BqVomAWxcKOR1KbZJyCEnCv04yks7Y1NhJ3JzxbDs307W67uX0JzklFdCg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.4.0", - "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0" - } - }, - "@azure/core-tracing": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", - "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", - "requires": { - "tslib": "^2.2.0" - } - }, - "@azure/core-util": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.9.0.tgz", - "integrity": "sha512-AfalUQ1ZppaKuxPPMsFEUdX6GZPB3d9paR9d/TTL7Ow2De8cJaC7ibi7kWVlFAVPCYo31OcnGymc0R89DX8Oaw==", - "requires": { - "@azure/abort-controller": "^2.0.0", - "tslib": "^2.6.2" - }, - "dependencies": { - "@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "requires": { - "tslib": "^2.6.2" - } - } - } - }, - "@azure/identity": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.2.1.tgz", - "integrity": "sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.5.0", - "@azure/core-client": "^1.4.0", - "@azure/core-rest-pipeline": "^1.1.0", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.3.0", - "@azure/logger": "^1.0.0", - "@azure/msal-browser": "^3.11.1", - "@azure/msal-node": "^2.9.2", - "events": "^3.0.0", - "jws": "^4.0.0", - "open": "^8.0.0", - "stoppable": "^1.1.0", - "tslib": "^2.2.0" - } - }, - "@azure/keyvault-secrets": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@azure/keyvault-secrets/-/keyvault-secrets-4.7.0.tgz", - "integrity": "sha512-YvlFXRQ+SI5NT4GtSFbb6HGo6prW3yzDab8tr6vga2/SjDQew3wJsCAAr/xwZz6XshFXCYEX26CDKmPf+SJKJg==", - "requires": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.5.0", - "@azure/core-http-compat": "^1.3.0", - "@azure/core-lro": "^2.2.0", - "@azure/core-paging": "^1.1.1", - "@azure/core-rest-pipeline": "^1.8.0", - "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", - "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" - } - }, - "@azure/logger": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", - "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", - "requires": { - "tslib": "^2.2.0" - } - }, - "@azure/msal-browser": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.13.0.tgz", - "integrity": "sha512-fD906nmJei3yE7la6DZTdUtXKvpwzJURkfsiz9747Icv4pit77cegSm6prJTKLQ1fw4iiZzrrWwxnhMLrTf5gQ==", - "requires": { - "@azure/msal-common": "14.9.0" - } - }, - "@azure/msal-common": { - "version": "14.9.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.9.0.tgz", - "integrity": "sha512-yzBPRlWPnTBeixxLNI3BBIgF5/bHpbhoRVuuDBnYjCyWRavaPUsKAHUDYLqpGkBLDciA6TCc6GOxN4/S3WiSxg==" - }, - "@azure/msal-node": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.9.2.tgz", - "integrity": "sha512-8tvi6Cos3m+0KmRbPjgkySXi+UQU/QiuVRFnrxIwt5xZlEEFa69O04RTaNESGgImyBBlYbo2mfE8/U8Bbdk1WQ==", - "requires": { - "@azure/msal-common": "14.12.0", - "jsonwebtoken": "^9.0.0", - "uuid": "^8.3.0" - }, - "dependencies": { - "@azure/msal-common": { - "version": "14.12.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.12.0.tgz", - "integrity": "sha512-IDDXmzfdwmDkv4SSmMEyAniJf6fDu3FJ7ncOjlxkDuT85uSnLEhZi3fGZpoR7T4XZpOMx9teM9GXBgrfJgyeBw==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, - "@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "optional": true, - "requires": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "optional": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "optional": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "optional": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "optional": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "optional": true - }, - "@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", - "dev": true, - "optional": true, - "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "optional": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "optional": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "optional": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "optional": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", - "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.12", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.12.tgz", - "integrity": "sha512-NlGesA1usRNn6ctHCZ21M4/dKPgW9Nn1FypRdIKKgZOKzkVV4T1FlK5mBiLhHBCDmEbdQG0idrcXlbZfksJ+RA==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.0", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.0.tgz", - "integrity": "sha512-9S9QrXY2K0L4AGDcSgTi9vgiCcG8VcBv4Mp7/1hDPYoswIy6Z6KO5blYto82BT8M0MZNRWmCFLpCs3HlpYGGdw==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, - "@rollup/plugin-typescript": { - "version": "11.1.5", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.5.tgz", - "integrity": "sha512-rnMHrGBB0IUEv69Q8/JGRD/n4/n6b3nfpufUu26axhUcboUzv/twfZU8fIBbTOphRAe0v8EyxzeDpKXqGHfyDA==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^5.0.1", - "resolve": "^1.22.1" - } - }, - "@rollup/pluginutils": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.5.tgz", - "integrity": "sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==", - "dev": true, - "requires": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - } - }, - "@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@sinonjs/samsam": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", - "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", - "dev": true, - "requires": { - "@sinonjs/commons": "^2.0.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - }, - "dependencies": { - "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - } - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, - "@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", - "dev": true - }, - "@types/mocha": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.4.tgz", - "integrity": "sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==", - "dev": true - }, - "@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", - "dev": true, - "requires": { - "undici-types": "~5.25.1" - } - }, - "@types/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", - "dev": true - }, - "@types/sinon": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.1.tgz", - "integrity": "sha512-Q2Go6TJetYn5Za1+RJA1Aik61Oa2FS8SuJ0juIqUuJ5dZR4wvhKfmSdIqWtQ3P6gljKWjW0/R7FZkA4oXVL6OA==", - "dev": true, - "requires": { - "@types/sinonjs__fake-timers": "*" - } - }, - "@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "dev": true - }, - "@types/uuid": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", - "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", - "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/type-utils": "6.8.0", - "@typescript-eslint/utils": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/parser": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", - "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", - "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", - "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "6.8.0", - "@typescript-eslint/utils": "6.8.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/types": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", - "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", - "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/visitor-keys": "6.8.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - } - }, - "@typescript-eslint/utils": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", - "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.8.0", - "@typescript-eslint/types": "6.8.0", - "@typescript-eslint/typescript-estree": "6.8.0", - "semver": "^7.5.4" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", - "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "6.8.0", - "eslint-visitor-keys": "^3.4.1" - } - }, - "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "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==", - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "requires": { - "fill-range": "^7.1.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - } - }, - "chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "dev": true, - "requires": { - "check-error": "^1.0.2" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "requires": { - "get-func-name": "^2.0.2" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "dev": true - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - } - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", - "dev": true, - "requires": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "optional": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "dependencies": { - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - } - } - }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "requires": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "requires": { - "get-func-name": "^2.0.1" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", - "dev": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - } - } - }, - "nock": { - "version": "13.3.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.6.tgz", - "integrity": "sha512-lT6YuktKroUFM+27mubf2uqQZVy2Jf+pfGzuh9N6VwdHlFoZqvi4zyxFTVR1w/ChPqGY6yxGehHp6C3wqCASCw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "propagate": "^2.0.0" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "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" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, - "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", - "dev": true - } - } - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, - "requires": { - "glob": "^10.3.7" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "rollup-plugin-dts": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-5.3.1.tgz", - "integrity": "sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.22.5", - "magic-string": "^0.30.2" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "sinon": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.2.0.tgz", - "integrity": "sha512-nPS85arNqwBXaIsFCkolHjGIkFo+Oxu9vbgmBJizLAhqe6P2o3Qmj3KCUoRkfhHtvgDhZdWD3risLHAUJ8npjw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.3.0", - "@sinonjs/samsam": "^8.0.0", - "diff": "^5.1.0", - "nise": "^5.1.4", - "supports-color": "^7.2.0" - }, - "dependencies": { - "diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "dev": true - } - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "stoppable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", - "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", - "dev": true, - "requires": {} - }, - "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true - }, - "undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } diff --git a/package.json b/package.json index 74aca6ec..27770a5f 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "devDependencies": { "@rollup/plugin-typescript": "^11.1.2", "@types/mocha": "^10.0.4", - "@types/node": "^20.5.7", + "@types/node": "^22.7.7", "@types/sinon": "^17.0.1", "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.6.0", @@ -47,11 +47,11 @@ "mocha": "^10.2.0", "nock": "^13.3.3", "rimraf": "^5.0.1", - "rollup": "^3.26.3", + "rollup": "^3.29.5", "rollup-plugin-dts": "^5.3.0", "sinon": "^15.2.0", "tslib": "^2.6.0", - "typescript": "^5.1.6", + "typescript": "^5.6.3", "uuid": "^9.0.1" }, "dependencies": { diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index 4a0acc04..1bbf0779 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -140,19 +140,19 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { return this.#configMap.size; } - entries(): IterableIterator<[string, any]> { + entries(): MapIterator<[string, any]> { return this.#configMap.entries(); } - keys(): IterableIterator { + keys(): MapIterator { return this.#configMap.keys(); } - values(): IterableIterator { + values(): MapIterator { return this.#configMap.values(); } - [Symbol.iterator](): IterableIterator<[string, any]> { + [Symbol.iterator](): MapIterator<[string, any]> { return this.#configMap[Symbol.iterator](); } // #endregion From b9ed65db08cd8ae8cfe02b560094dbfc39218eba Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <141655842+zhiyuanliang-ms@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:40:55 +0800 Subject: [PATCH 14/16] add requestTracingOptions (#114) --- src/AzureAppConfigurationImpl.ts | 2 +- src/AzureAppConfigurationOptions.ts | 6 ++++++ src/requestTracing/RequestTracingOptions.ts | 12 ++++++++++++ test/requestTracing.test.ts | 14 ++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/requestTracing/RequestTracingOptions.ts diff --git a/src/AzureAppConfigurationImpl.ts b/src/AzureAppConfigurationImpl.ts index 1bbf0779..3d5bc211 100644 --- a/src/AzureAppConfigurationImpl.ts +++ b/src/AzureAppConfigurationImpl.ts @@ -63,7 +63,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration { this.#options = options; // Enable request tracing if not opt-out - this.#requestTracingEnabled = requestTracingEnabled(); + this.#requestTracingEnabled = options?.requestTracingOptions?.enabled ?? requestTracingEnabled(); if (options?.trimKeyPrefixes) { this.#sortedTrimKeyPrefixes = [...options.trimKeyPrefixes].sort((a, b) => b.localeCompare(a)); diff --git a/src/AzureAppConfigurationOptions.ts b/src/AzureAppConfigurationOptions.ts index f88ad67c..a9df321d 100644 --- a/src/AzureAppConfigurationOptions.ts +++ b/src/AzureAppConfigurationOptions.ts @@ -6,6 +6,7 @@ import { KeyVaultOptions } from "./keyvault/KeyVaultOptions.js"; import { RefreshOptions } from "./RefreshOptions.js"; import { SettingSelector } from "./types.js"; import { FeatureFlagOptions } from "./featureManagement/FeatureFlagOptions.js"; +import { RequestTracingOptions } from "./requestTracing/RequestTracingOptions.js"; export const MaxRetries = 2; export const MaxRetryDelayInMs = 60000; @@ -47,4 +48,9 @@ export interface AzureAppConfigurationOptions { * Specifies options used to configure feature flags. */ featureFlagOptions?: FeatureFlagOptions; + + /** + * Specifies options used to configure request tracing. + */ + requestTracingOptions?: RequestTracingOptions; } diff --git a/src/requestTracing/RequestTracingOptions.ts b/src/requestTracing/RequestTracingOptions.ts new file mode 100644 index 00000000..016da0cd --- /dev/null +++ b/src/requestTracing/RequestTracingOptions.ts @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +/** + * Options used to configure request tracing. + */ +export interface RequestTracingOptions { + /** + * Specifies whether request tracing is enabled. + */ + enabled: boolean; +} diff --git a/test/requestTracing.test.ts b/test/requestTracing.test.ts index d4e7edcf..a08ffa8b 100644 --- a/test/requestTracing.test.ts +++ b/test/requestTracing.test.ts @@ -122,6 +122,20 @@ describe("request tracing", function () { delete process.env.AZURE_APP_CONFIGURATION_TRACING_DISABLED; }); + it("should disable request tracing by RequestTracingOptions", async () => { + try { + await load(createMockedConnectionString(fakeEndpoint), { + clientOptions, + requestTracingOptions: { + enabled: false + } + }); + } catch (e) { /* empty */ } + expect(headerPolicy.headers).not.undefined; + const correlationContext = headerPolicy.headers.get("Correlation-Context"); + expect(correlationContext).undefined; + }); + it("should have request type in correlation-context header when refresh is enabled", async () => { mockAppConfigurationClientListConfigurationSettings([{ key: "app.settings.fontColor", From 477e48cd5ac682e6d4fcbaf6d6a17bd0bc6e012a Mon Sep 17 00:00:00 2001 From: linglingye001 <143174321+linglingye001@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:54:26 +0800 Subject: [PATCH 15/16] update * bump up version 1.1.1 * update --- package-lock.json | 2 +- package.json | 2 +- src/version.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d36f2b4b..b587455c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.1.0", + "version": "1.1.1", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index 27770a5f..25302993 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azure/app-configuration-provider", - "version": "1.1.0", + "version": "1.1.1", "description": "The JavaScript configuration provider for Azure App Configuration", "main": "dist/index.js", "module": "./dist-esm/index.js", diff --git a/src/version.ts b/src/version.ts index 29eba990..afee11aa 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,4 +1,4 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -export const VERSION = "1.1.0"; +export const VERSION = "1.1.1"; From 6f5dac2f189a13862a7c673604866399fe854fa1 Mon Sep 17 00:00:00 2001 From: "Lingling Ye (from Dev Box)" Date: Fri, 17 Jan 2025 19:59:54 +0800 Subject: [PATCH 16/16] add example --- examples/nuxt-example/.editorconfig | 13 + examples/nuxt-example/.nuxt/App.js | 210 +++++ examples/nuxt-example/.nuxt/client.js | 891 ++++++++++++++++++ .../nuxt-example/.nuxt/components/index.js | 34 + .../.nuxt/components/nuxt-build-indicator.vue | 143 +++ .../.nuxt/components/nuxt-child.js | 121 +++ .../.nuxt/components/nuxt-error.vue | 98 ++ .../.nuxt/components/nuxt-link.client.js | 98 ++ .../.nuxt/components/nuxt-link.server.js | 16 + .../.nuxt/components/nuxt-loading.vue | 178 ++++ .../nuxt-example/.nuxt/components/nuxt.js | 102 ++ .../nuxt-example/.nuxt/components/plugin.js | 7 + .../nuxt-example/.nuxt/components/readme.md | 11 + examples/nuxt-example/.nuxt/empty.js | 1 + examples/nuxt-example/.nuxt/index.js | 228 +++++ examples/nuxt-example/.nuxt/jsonp.js | 82 ++ examples/nuxt-example/.nuxt/loading.html | 110 +++ examples/nuxt-example/.nuxt/middleware.js | 3 + .../nuxt-example/.nuxt/mixins/fetch.client.js | 90 ++ .../nuxt-example/.nuxt/mixins/fetch.server.js | 69 ++ examples/nuxt-example/.nuxt/router.js | 53 ++ .../.nuxt/router.scrollBehavior.js | 82 ++ examples/nuxt-example/.nuxt/routes.json | 16 + examples/nuxt-example/.nuxt/server.js | 296 ++++++ examples/nuxt-example/.nuxt/utils.js | 637 +++++++++++++ examples/nuxt-example/.nuxt/vetur/tags.json | 11 + .../.nuxt/views/app.template.html | 9 + examples/nuxt-example/.nuxt/views/error.html | 23 + examples/nuxt-example/README.md | 69 ++ examples/nuxt-example/components/NavBar.vue | 29 + examples/nuxt-example/components/NuxtLogo.vue | 11 + examples/nuxt-example/components/Tutorial.vue | 52 + examples/nuxt-example/layouts/default.vue | 32 + examples/nuxt-example/nuxt.config.js | 50 + examples/nuxt-example/package.json | 26 + examples/nuxt-example/pages/about.vue | 20 + examples/nuxt-example/pages/index.vue | 29 + examples/nuxt-example/static/favicon.ico | Bin 0 -> 8636 bytes examples/nuxt-example/store/README.md | 10 + 39 files changed, 3960 insertions(+) create mode 100644 examples/nuxt-example/.editorconfig create mode 100644 examples/nuxt-example/.nuxt/App.js create mode 100644 examples/nuxt-example/.nuxt/client.js create mode 100644 examples/nuxt-example/.nuxt/components/index.js create mode 100644 examples/nuxt-example/.nuxt/components/nuxt-build-indicator.vue create mode 100644 examples/nuxt-example/.nuxt/components/nuxt-child.js create mode 100644 examples/nuxt-example/.nuxt/components/nuxt-error.vue create mode 100644 examples/nuxt-example/.nuxt/components/nuxt-link.client.js create mode 100644 examples/nuxt-example/.nuxt/components/nuxt-link.server.js create mode 100644 examples/nuxt-example/.nuxt/components/nuxt-loading.vue create mode 100644 examples/nuxt-example/.nuxt/components/nuxt.js create mode 100644 examples/nuxt-example/.nuxt/components/plugin.js create mode 100644 examples/nuxt-example/.nuxt/components/readme.md create mode 100644 examples/nuxt-example/.nuxt/empty.js create mode 100644 examples/nuxt-example/.nuxt/index.js create mode 100644 examples/nuxt-example/.nuxt/jsonp.js create mode 100644 examples/nuxt-example/.nuxt/loading.html create mode 100644 examples/nuxt-example/.nuxt/middleware.js create mode 100644 examples/nuxt-example/.nuxt/mixins/fetch.client.js create mode 100644 examples/nuxt-example/.nuxt/mixins/fetch.server.js create mode 100644 examples/nuxt-example/.nuxt/router.js create mode 100644 examples/nuxt-example/.nuxt/router.scrollBehavior.js create mode 100644 examples/nuxt-example/.nuxt/routes.json create mode 100644 examples/nuxt-example/.nuxt/server.js create mode 100644 examples/nuxt-example/.nuxt/utils.js create mode 100644 examples/nuxt-example/.nuxt/vetur/tags.json create mode 100644 examples/nuxt-example/.nuxt/views/app.template.html create mode 100644 examples/nuxt-example/.nuxt/views/error.html create mode 100644 examples/nuxt-example/README.md create mode 100644 examples/nuxt-example/components/NavBar.vue create mode 100644 examples/nuxt-example/components/NuxtLogo.vue create mode 100644 examples/nuxt-example/components/Tutorial.vue create mode 100644 examples/nuxt-example/layouts/default.vue create mode 100644 examples/nuxt-example/nuxt.config.js create mode 100644 examples/nuxt-example/package.json create mode 100644 examples/nuxt-example/pages/about.vue create mode 100644 examples/nuxt-example/pages/index.vue create mode 100644 examples/nuxt-example/static/favicon.ico create mode 100644 examples/nuxt-example/store/README.md diff --git a/examples/nuxt-example/.editorconfig b/examples/nuxt-example/.editorconfig new file mode 100644 index 00000000..5d126348 --- /dev/null +++ b/examples/nuxt-example/.editorconfig @@ -0,0 +1,13 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/examples/nuxt-example/.nuxt/App.js b/examples/nuxt-example/.nuxt/App.js new file mode 100644 index 00000000..3d323a3a --- /dev/null +++ b/examples/nuxt-example/.nuxt/App.js @@ -0,0 +1,210 @@ +import Vue from 'vue' +import { decode, parsePath, withoutBase, withoutTrailingSlash, normalizeURL } from 'ufo' + +import { getMatchedComponentsInstances, getChildrenComponentInstancesUsingFetch, promisify, globalHandleError, urlJoin, sanitizeComponent } from './utils' +import NuxtError from './components/nuxt-error.vue' +import NuxtLoading from './components/nuxt-loading.vue' +import NuxtBuildIndicator from './components/nuxt-build-indicator' + +import _6f6c098b from '..\\layouts\\default.vue' + +const layouts = { "_default": sanitizeComponent(_6f6c098b) } + +export default { + render (h, props) { + const loadingEl = h('NuxtLoading', { ref: 'loading' }) + + const layoutEl = h(this.layout || 'nuxt') + const templateEl = h('div', { + domProps: { + id: '__layout' + }, + key: this.layoutName + }, [layoutEl]) + + const transitionEl = h('transition', { + props: { + name: 'layout', + mode: 'out-in' + }, + on: { + beforeEnter (el) { + // Ensure to trigger scroll event after calling scrollBehavior + window.$nuxt.$nextTick(() => { + window.$nuxt.$emit('triggerScroll') + }) + } + } + }, [templateEl]) + + return h('div', { + domProps: { + id: '__nuxt' + } + }, [ + loadingEl, + h(NuxtBuildIndicator), + transitionEl + ]) + }, + + data: () => ({ + isOnline: true, + + layout: null, + layoutName: '', + + nbFetching: 0 + }), + + beforeCreate () { + Vue.util.defineReactive(this, 'nuxt', this.$options.nuxt) + }, + created () { + // Add this.$nuxt in child instances + this.$root.$options.$nuxt = this + + if (process.client) { + // add to window so we can listen when ready + window.$nuxt = this + + this.refreshOnlineStatus() + // Setup the listeners + window.addEventListener('online', this.refreshOnlineStatus) + window.addEventListener('offline', this.refreshOnlineStatus) + } + // Add $nuxt.error() + this.error = this.nuxt.error + // Add $nuxt.context + this.context = this.$options.context + }, + + async mounted () { + this.$loading = this.$refs.loading + }, + + watch: { + 'nuxt.err': 'errorChanged' + }, + + computed: { + isOffline () { + return !this.isOnline + }, + + isFetching () { + return this.nbFetching > 0 + }, + }, + + methods: { + refreshOnlineStatus () { + if (process.client) { + if (typeof window.navigator.onLine === 'undefined') { + // If the browser doesn't support connection status reports + // assume that we are online because most apps' only react + // when they now that the connection has been interrupted + this.isOnline = true + } else { + this.isOnline = window.navigator.onLine + } + } + }, + + async refresh () { + const pages = getMatchedComponentsInstances(this.$route) + + if (!pages.length) { + return + } + this.$loading.start() + + const promises = pages.map(async (page) => { + let p = [] + + // Old fetch + if (page.$options.fetch && page.$options.fetch.length) { + p.push(promisify(page.$options.fetch, this.context)) + } + + if (page.$options.asyncData) { + p.push( + promisify(page.$options.asyncData, this.context) + .then((newData) => { + for (const key in newData) { + Vue.set(page.$data, key, newData[key]) + } + }) + ) + } + + // Wait for asyncData & old fetch to finish + await Promise.all(p) + // Cleanup refs + p = [] + + if (page.$fetch) { + p.push(page.$fetch()) + } + // Get all component instance to call $fetch + for (const component of getChildrenComponentInstancesUsingFetch(page.$vnode.componentInstance)) { + p.push(component.$fetch()) + } + + return Promise.all(p) + }) + try { + await Promise.all(promises) + } catch (error) { + this.$loading.fail(error) + globalHandleError(error) + this.error(error) + } + this.$loading.finish() + }, + errorChanged () { + if (this.nuxt.err) { + if (this.$loading) { + if (this.$loading.fail) { + this.$loading.fail(this.nuxt.err) + } + if (this.$loading.finish) { + this.$loading.finish() + } + } + + let errorLayout = (NuxtError.options || NuxtError).layout; + + if (typeof errorLayout === 'function') { + errorLayout = errorLayout(this.context) + } + + this.nuxt.errPageReady = true + this.setLayout(errorLayout) + } + }, + + setLayout (layout) { + if(layout && typeof layout !== 'string') { + throw new Error('[nuxt] Avoid using non-string value as layout property.') + } + + if (!layout || !layouts['_' + layout]) { + layout = 'default' + } + this.layoutName = layout + this.layout = layouts['_' + layout] + return this.layout + }, + loadLayout (layout) { + if (!layout || !layouts['_' + layout]) { + layout = 'default' + } + return Promise.resolve(layouts['_' + layout]) + }, + }, + + components: { + NuxtLoading + } +} diff --git a/examples/nuxt-example/.nuxt/client.js b/examples/nuxt-example/.nuxt/client.js new file mode 100644 index 00000000..3cdc1dea --- /dev/null +++ b/examples/nuxt-example/.nuxt/client.js @@ -0,0 +1,891 @@ +import Vue from 'vue' +import fetch from 'unfetch' +import middleware from './middleware.js' +import { + applyAsyncData, + promisify, + middlewareSeries, + sanitizeComponent, + resolveRouteComponents, + getMatchedComponents, + getMatchedComponentsInstances, + flatMapComponents, + setContext, + getLocation, + compile, + getQueryDiff, + globalHandleError, + isSamePath, + urlJoin +} from './utils.js' +import { createApp, NuxtError } from './index.js' +import fetchMixin from './mixins/fetch.client' +import NuxtLink from './components/nuxt-link.client.js' // should be included after ./index.js + +// Fetch mixin +if (!Vue.__nuxt__fetch__mixin__) { + Vue.mixin(fetchMixin) + Vue.__nuxt__fetch__mixin__ = true +} + +// Component: +Vue.component(NuxtLink.name, NuxtLink) +Vue.component('NLink', NuxtLink) + +if (!global.fetch) { global.fetch = fetch } + +// Global shared references +let _lastPaths = [] +let app +let router + +// Try to rehydrate SSR data from window +const NUXT = window.__NUXT__ || {} + +const $config = NUXT.config || {} +if ($config._app) { + __webpack_public_path__ = urlJoin($config._app.cdnURL, $config._app.assetsPath) +} + +Object.assign(Vue.config, {"silent":false,"performance":true}) + +const logs = NUXT.logs || [] + if (logs.length > 0) { + const ssrLogStyle = 'background: #2E495E;border-radius: 0.5em;color: white;font-weight: bold;padding: 2px 0.5em;' + console.group && console.group ('%cNuxt SSR', ssrLogStyle) + logs.forEach(logObj => (console[logObj.type] || console.log)(...logObj.args)) + delete NUXT.logs + console.groupEnd && console.groupEnd() +} + +// Setup global Vue error handler +if (!Vue.config.$nuxt) { + const defaultErrorHandler = Vue.config.errorHandler + Vue.config.errorHandler = async (err, vm, info, ...rest) => { + // Call other handler if exist + let handled = null + if (typeof defaultErrorHandler === 'function') { + handled = defaultErrorHandler(err, vm, info, ...rest) + } + if (handled === true) { + return handled + } + + if (vm && vm.$root) { + const nuxtApp = Object.keys(Vue.config.$nuxt) + .find(nuxtInstance => vm.$root[nuxtInstance]) + + // Show Nuxt Error Page + if (nuxtApp && vm.$root[nuxtApp].error && info !== 'render function') { + const currentApp = vm.$root[nuxtApp] + + // Load error layout + let layout = (NuxtError.options || NuxtError).layout + if (typeof layout === 'function') { + layout = layout(currentApp.context) + } + if (layout) { + await currentApp.loadLayout(layout).catch(() => {}) + } + currentApp.setLayout(layout) + + currentApp.error(err) + } + } + + if (typeof defaultErrorHandler === 'function') { + return handled + } + + // Log to console + if (process.env.NODE_ENV !== 'production') { + console.error(err) + } else { + console.error(err.message || err) + } + } + Vue.config.$nuxt = {} +} +Vue.config.$nuxt.$nuxt = true + +const errorHandler = Vue.config.errorHandler || console.error + +// Create and mount App +createApp(null, NUXT.config).then(mountApp).catch(errorHandler) + +function componentOption (component, key, ...args) { + if (!component || !component.options || !component.options[key]) { + return {} + } + const option = component.options[key] + if (typeof option === 'function') { + return option(...args) + } + return option +} + +function mapTransitions (toComponents, to, from) { + const componentTransitions = (component) => { + const transition = componentOption(component, 'transition', to, from) || {} + return (typeof transition === 'string' ? { name: transition } : transition) + } + + const fromComponents = from ? getMatchedComponents(from) : [] + const maxDepth = Math.max(toComponents.length, fromComponents.length) + + const mergedTransitions = [] + for (let i=0; i typeof toTransitions[key] !== 'undefined' && !key.toLowerCase().includes('leave')) + .forEach((key) => { transitions[key] = toTransitions[key] }) + + mergedTransitions.push(transitions) + } + return mergedTransitions +} + +async function loadAsyncComponents (to, from, next) { + // Check if route changed (this._routeChanged), only if the page is not an error (for validate()) + this._routeChanged = Boolean(app.nuxt.err) || from.name !== to.name + this._paramChanged = !this._routeChanged && from.path !== to.path + this._queryChanged = !this._paramChanged && from.fullPath !== to.fullPath + this._diffQuery = (this._queryChanged ? getQueryDiff(to.query, from.query) : []) + + if ((this._routeChanged || this._paramChanged) && this.$loading.start && !this.$loading.manual) { + this.$loading.start() + } + + try { + if (this._queryChanged) { + const Components = await resolveRouteComponents( + to, + (Component, instance) => ({ Component, instance }) + ) + // Add a marker on each component that it needs to refresh or not + const startLoader = Components.some(({ Component, instance }) => { + const watchQuery = Component.options.watchQuery + if (watchQuery === true) { + return true + } + if (Array.isArray(watchQuery)) { + return watchQuery.some(key => this._diffQuery[key]) + } + if (typeof watchQuery === 'function') { + return watchQuery.apply(instance, [to.query, from.query]) + } + return false + }) + + if (startLoader && this.$loading.start && !this.$loading.manual) { + this.$loading.start() + } + } + // Call next() + next() + } catch (error) { + const err = error || {} + const statusCode = err.statusCode || err.status || (err.response && err.response.status) || 500 + const message = err.message || '' + + // Handle chunk loading errors + // This may be due to a new deployment or a network problem + if (/^Loading( CSS)? chunk (\d)+ failed\./.test(message)) { + window.location.reload(true /* skip cache */) + return // prevent error page blinking for user + } + + this.error({ statusCode, message }) + this.$nuxt.$emit('routeChanged', to, from, err) + next() + } +} + +function applySSRData (Component, ssrData) { + if (NUXT.serverRendered && ssrData) { + applyAsyncData(Component, ssrData) + } + + Component._Ctor = Component + return Component +} + +// Get matched components +function resolveComponents (route) { + return flatMapComponents(route, async (Component, _, match, key, index) => { + // If component is not resolved yet, resolve it + if (typeof Component === 'function' && !Component.options) { + Component = await Component() + } + // Sanitize it and save it + const _Component = applySSRData(sanitizeComponent(Component), NUXT.data ? NUXT.data[index] : null) + match.components[key] = _Component + return _Component + }) +} + +function callMiddleware (Components, context, layout, renderState) { + let midd = [] + let unknownMiddleware = false + + // If layout is undefined, only call global middleware + if (typeof layout !== 'undefined') { + midd = [] // Exclude global middleware if layout defined (already called before) + layout = sanitizeComponent(layout) + if (layout.options.middleware) { + midd = midd.concat(layout.options.middleware) + } + Components.forEach((Component) => { + if (Component.options.middleware) { + midd = midd.concat(Component.options.middleware) + } + }) + } + + midd = midd.map((name) => { + if (typeof name === 'function') { + return name + } + if (typeof middleware[name] !== 'function') { + unknownMiddleware = true + this.error({ statusCode: 500, message: 'Unknown middleware ' + name }) + } + return middleware[name] + }) + + if (unknownMiddleware) { + return + } + return middlewareSeries(midd, context, renderState) +} + +async function render (to, from, next, renderState) { + if (this._routeChanged === false && this._paramChanged === false && this._queryChanged === false) { + return next() + } + // Handle first render on SPA mode + let spaFallback = false + if (to === from) { + _lastPaths = [] + spaFallback = true + } else { + const fromMatches = [] + _lastPaths = getMatchedComponents(from, fromMatches).map((Component, i) => { + return compile(from.matched[fromMatches[i]].path)(from.params) + }) + } + + // nextCalled is true when redirected + let nextCalled = false + const _next = (path) => { + if (from.path === path.path && this.$loading.finish) { + this.$loading.finish() + } + + if (from.path !== path.path && this.$loading.pause) { + this.$loading.pause() + } + + if (nextCalled) { + return + } + + nextCalled = true + next(path) + } + + // Update context + await setContext(app, { + route: to, + from, + error: (err) => { + if (renderState.aborted) { + return + } + app.nuxt.error.call(this, err) + }, + next: _next.bind(this) + }) + this._dateLastError = app.nuxt.dateErr + this._hadError = Boolean(app.nuxt.err) + + // Get route's matched components + const matches = [] + const Components = getMatchedComponents(to, matches) + + // If no Components matched, generate 404 + if (!Components.length) { + // Default layout + await callMiddleware.call(this, Components, app.context, undefined, renderState) + if (nextCalled) { + return + } + if (renderState.aborted) { + next(false) + return + } + + // Load layout for error page + const errorLayout = (NuxtError.options || NuxtError).layout + const layout = await this.loadLayout( + typeof errorLayout === 'function' + ? errorLayout.call(NuxtError, app.context) + : errorLayout + ) + + await callMiddleware.call(this, Components, app.context, layout, renderState) + if (nextCalled) { + return + } + if (renderState.aborted) { + next(false) + return + } + + // Show error page + app.context.error({ statusCode: 404, message: 'This page could not be found' }) + return next() + } + + // Update ._data and other properties if hot reloaded + Components.forEach((Component) => { + if (Component._Ctor && Component._Ctor.options) { + Component.options.asyncData = Component._Ctor.options.asyncData + Component.options.fetch = Component._Ctor.options.fetch + } + }) + + // Apply transitions + this.setTransitions(mapTransitions(Components, to, from)) + + try { + // Call middleware + await callMiddleware.call(this, Components, app.context, undefined, renderState) + if (nextCalled) { + return + } + if (renderState.aborted) { + next(false) + return + } + if (app.context._errored) { + return next() + } + + // Set layout + let layout = Components[0].options.layout + if (typeof layout === 'function') { + layout = layout(app.context) + } + layout = await this.loadLayout(layout) + + // Call middleware for layout + await callMiddleware.call(this, Components, app.context, layout, renderState) + if (nextCalled) { + return + } + if (renderState.aborted) { + next(false) + return + } + if (app.context._errored) { + return next() + } + + // Call .validate() + let isValid = true + try { + for (const Component of Components) { + if (typeof Component.options.validate !== 'function') { + continue + } + + isValid = await Component.options.validate(app.context) + + if (!isValid) { + break + } + } + } catch (validationError) { + // ...If .validate() threw an error + this.error({ + statusCode: validationError.statusCode || '500', + message: validationError.message + }) + return next() + } + + // ...If .validate() returned false + if (!isValid) { + this.error({ statusCode: 404, message: 'This page could not be found' }) + return next() + } + + let instances + // Call asyncData & fetch hooks on components matched by the route. + await Promise.all(Components.map(async (Component, i) => { + // Check if only children route changed + Component._path = compile(to.matched[matches[i]].path)(to.params) + Component._dataRefresh = false + const childPathChanged = Component._path !== _lastPaths[i] + // Refresh component (call asyncData & fetch) when: + // Route path changed part includes current component + // Or route param changed part includes current component and watchParam is not `false` + // Or route query is changed and watchQuery returns `true` + if (this._routeChanged && childPathChanged) { + Component._dataRefresh = true + } else if (this._paramChanged && childPathChanged) { + const watchParam = Component.options.watchParam + Component._dataRefresh = watchParam !== false + } else if (this._queryChanged) { + const watchQuery = Component.options.watchQuery + if (watchQuery === true) { + Component._dataRefresh = true + } else if (Array.isArray(watchQuery)) { + Component._dataRefresh = watchQuery.some(key => this._diffQuery[key]) + } else if (typeof watchQuery === 'function') { + if (!instances) { + instances = getMatchedComponentsInstances(to) + } + Component._dataRefresh = watchQuery.apply(instances[i], [to.query, from.query]) + } + } + if (!this._hadError && this._isMounted && !Component._dataRefresh) { + return + } + + const promises = [] + + const hasAsyncData = ( + Component.options.asyncData && + typeof Component.options.asyncData === 'function' + ) + + const hasFetch = Boolean(Component.options.fetch) && Component.options.fetch.length + + const loadingIncrease = (hasAsyncData && hasFetch) ? 30 : 45 + + // Call asyncData(context) + if (hasAsyncData) { + const promise = promisify(Component.options.asyncData, app.context) + + promise.then((asyncDataResult) => { + applyAsyncData(Component, asyncDataResult) + + if (this.$loading.increase) { + this.$loading.increase(loadingIncrease) + } + }) + promises.push(promise) + } + + // Check disabled page loading + this.$loading.manual = Component.options.loading === false + + // Call fetch(context) + if (hasFetch) { + let p = Component.options.fetch(app.context) + if (!p || (!(p instanceof Promise) && (typeof p.then !== 'function'))) { + p = Promise.resolve(p) + } + p.then((fetchResult) => { + if (this.$loading.increase) { + this.$loading.increase(loadingIncrease) + } + }) + promises.push(p) + } + + return Promise.all(promises) + })) + + // If not redirected + if (!nextCalled) { + if (this.$loading.finish && !this.$loading.manual) { + this.$loading.finish() + } + + if (renderState.aborted) { + next(false) + return + } + next() + } + } catch (err) { + if (renderState.aborted) { + next(false) + return + } + const error = err || {} + if (error.message === 'ERR_REDIRECT') { + return this.$nuxt.$emit('routeChanged', to, from, error) + } + _lastPaths = [] + + globalHandleError(error) + + // Load error layout + let layout = (NuxtError.options || NuxtError).layout + if (typeof layout === 'function') { + layout = layout(app.context) + } + await this.loadLayout(layout) + + this.error(error) + this.$nuxt.$emit('routeChanged', to, from, error) + next() + } +} + +// Fix components format in matched, it's due to code-splitting of vue-router +function normalizeComponents (to, ___) { + flatMapComponents(to, (Component, _, match, key) => { + if (typeof Component === 'object' && !Component.options) { + // Updated via vue-router resolveAsyncComponents() + Component = Vue.extend(Component) + Component._Ctor = Component + match.components[key] = Component + } + return Component + }) +} + +const routeMap = new WeakMap() +function getLayoutForNextPage (to, from, next) { + // Set layout + let hasError = Boolean(this.$options.nuxt.err) + if (this._hadError && this._dateLastError === this.$options.nuxt.dateErr) { + hasError = false + } + let layout = hasError + ? (NuxtError.options || NuxtError).layout + : to.matched[0].components.default.options.layout + + if (typeof layout === 'function') { + layout = layout(app.context) + } + + routeMap.set(to, layout); + + if (next) next(); +} + +function setLayoutForNextPage(to) { + const layout = routeMap.get(to) + routeMap.delete(to) + + const prevPageIsError = this._hadError && this._dateLastError === this.$options.nuxt.dateErr + + if (prevPageIsError) { + this.$options.nuxt.err = null + } + + this.setLayout(layout) +} + +function checkForErrors (app) { + // Hide error component if no error + if (app._hadError && app._dateLastError === app.$options.nuxt.dateErr) { + app.error() + } +} + +// When navigating on a different route but the same component is used, Vue.js +// Will not update the instance data, so we have to update $data ourselves +function fixPrepatch (to, ___) { + if (this._routeChanged === false && this._paramChanged === false && this._queryChanged === false) { + return + } + + const instances = getMatchedComponentsInstances(to) + const Components = getMatchedComponents(to) + + let triggerScroll = false + + Vue.nextTick(() => { + instances.forEach((instance, i) => { + if (!instance || instance._isDestroyed) { + return + } + + if ( + instance.constructor._dataRefresh && + Components[i] === instance.constructor && + instance.$vnode.data.keepAlive !== true && + typeof instance.constructor.options.data === 'function' + ) { + const newData = instance.constructor.options.data.call(instance) + for (const key in newData) { + Vue.set(instance.$data, key, newData[key]) + } + + triggerScroll = true + } + }) + + if (triggerScroll) { + // Ensure to trigger scroll event after calling scrollBehavior + window.$nuxt.$nextTick(() => { + window.$nuxt.$emit('triggerScroll') + }) + } + + checkForErrors(this) + + // Hot reloading + setTimeout(() => hotReloadAPI(this), 100) + }) +} + +function nuxtReady (_app) { + window.onNuxtReadyCbs.forEach((cb) => { + if (typeof cb === 'function') { + cb(_app) + } + }) + // Special JSDOM + if (typeof window._onNuxtLoaded === 'function') { + window._onNuxtLoaded(_app) + } + // Add router hooks + router.afterEach((to, from) => { + // Wait for fixPrepatch + $data updates + Vue.nextTick(() => _app.$nuxt.$emit('routeChanged', to, from)) + }) +} + +const noopData = () => { return {} } +const noopFetch = () => {} + +// Special hot reload with asyncData(context) +function getNuxtChildComponents ($parent, $components = []) { + $parent.$children.forEach(($child) => { + if ($child.$vnode && $child.$vnode.data.nuxtChild && !$components.find(c =>(c.$options.__file === $child.$options.__file))) { + $components.push($child) + } + if ($child.$children && $child.$children.length) { + getNuxtChildComponents($child, $components) + } + }) + + return $components +} + +function hotReloadAPI(_app) { + if (!module.hot) return + + let $components = getNuxtChildComponents(_app.$nuxt, []) + + $components.forEach(addHotReload.bind(_app)) + + if (_app.context.isHMR) { + const Components = getMatchedComponents(router.currentRoute) + Components.forEach((Component) => { + Component.prototype.constructor = Component + }) + } +} + +function addHotReload ($component, depth) { + if ($component.$vnode.data._hasHotReload) return + $component.$vnode.data._hasHotReload = true + + var _forceUpdate = $component.$forceUpdate.bind($component.$parent) + + $component.$vnode.context.$forceUpdate = async () => { + let Components = getMatchedComponents(router.currentRoute) + let Component = Components[depth] + if (!Component) { + return _forceUpdate() + } + if (typeof Component === 'object' && !Component.options) { + // Updated via vue-router resolveAsyncComponents() + Component = Vue.extend(Component) + Component._Ctor = Component + } + this.error() + let promises = [] + const next = function (path) { + this.$loading.finish && this.$loading.finish() + router.push(path) + } + await setContext(app, { + route: router.currentRoute, + isHMR: true, + next: next.bind(this) + }) + const context = app.context + + if (this.$loading.start && !this.$loading.manual) { + this.$loading.start() + } + + callMiddleware.call(this, Components, context) + .then(() => { + // If layout changed + if (depth !== 0) { + return + } + + let layout = Component.options.layout || 'default' + if (typeof layout === 'function') { + layout = layout(context) + } + if (this.layoutName === layout) { + return + } + let promise = this.loadLayout(layout) + promise.then(() => { + this.setLayout(layout) + Vue.nextTick(() => hotReloadAPI(this)) + }) + return promise + }) + + .then(() => { + return callMiddleware.call(this, Components, context, this.layout) + }) + + .then(() => { + // Call asyncData(context) + let pAsyncData = promisify(Component.options.asyncData || noopData, context) + pAsyncData.then((asyncDataResult) => { + applyAsyncData(Component, asyncDataResult) + this.$loading.increase && this.$loading.increase(30) + }) + promises.push(pAsyncData) + + // Call fetch() + Component.options.fetch = Component.options.fetch || noopFetch + let pFetch = Component.options.fetch.length && Component.options.fetch(context) + if (!pFetch || (!(pFetch instanceof Promise) && (typeof pFetch.then !== 'function'))) { pFetch = Promise.resolve(pFetch) } + pFetch.then(() => this.$loading.increase && this.$loading.increase(30)) + promises.push(pFetch) + + return Promise.all(promises) + }) + .then(() => { + this.$loading.finish && this.$loading.finish() + _forceUpdate() + setTimeout(() => hotReloadAPI(this), 100) + }) + } +} + +async function mountApp (__app) { + // Set global variables + app = __app.app + router = __app.router + + // Create Vue instance + const _app = new Vue(app) + + // Load layout + const layout = NUXT.layout || 'default' + await _app.loadLayout(layout) + _app.setLayout(layout) + + // Mounts Vue app to DOM element + const mount = () => { + _app.$mount('#__nuxt') + + // Add afterEach router hooks + router.afterEach(normalizeComponents) + + router.beforeResolve(getLayoutForNextPage.bind(_app)) + router.afterEach(setLayoutForNextPage.bind(_app)) + + router.afterEach(fixPrepatch.bind(_app)) + + // Listen for first Vue update + Vue.nextTick(() => { + // Call window.{{globals.readyCallback}} callbacks + nuxtReady(_app) + + // Enable hot reloading + hotReloadAPI(_app) + }) + } + + // Resolve route components + const Components = await Promise.all(resolveComponents(app.context.route)) + + // Enable transitions + _app.setTransitions = _app.$options.nuxt.setTransitions.bind(_app) + if (Components.length) { + _app.setTransitions(mapTransitions(Components, router.currentRoute)) + _lastPaths = router.currentRoute.matched.map(route => compile(route.path)(router.currentRoute.params)) + } + + // Initialize error handler + _app.$loading = {} // To avoid error while _app.$nuxt does not exist + if (NUXT.error) { + _app.error(NUXT.error) + _app.nuxt.errPageReady = true + } + + // Add beforeEach router hooks + router.beforeEach(loadAsyncComponents.bind(_app)) + + // Each new invocation of render() aborts previous invocation + let renderState = null + const boundRender = render.bind(_app) + router.beforeEach((to, from, next) => { + if (renderState) { + renderState.aborted = true + } + renderState = { aborted: false } + boundRender(to, from, next, renderState) + }) + + // Fix in static: remove trailing slash to force hydration + // Full static, if server-rendered: hydrate, to allow custom redirect to generated page + + // Fix in static: remove trailing slash to force hydration + if (NUXT.serverRendered && isSamePath(NUXT.routePath, _app.context.route.path)) { + return mount() + } + + const clientFirstLayoutSet = () => { + getLayoutForNextPage.call(_app, router.currentRoute) + setLayoutForNextPage.call(_app, router.currentRoute) + } + + // First render on client-side + const clientFirstMount = () => { + normalizeComponents(router.currentRoute, router.currentRoute) + clientFirstLayoutSet() + checkForErrors(_app) + // Don't call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render + mount() + } + + // fix: force next tick to avoid having same timestamp when an error happen on spa fallback + await new Promise(resolve => setTimeout(resolve, 0)) + render.call(_app, router.currentRoute, router.currentRoute, (path) => { + // If not redirected + if (!path) { + clientFirstMount() + return + } + + // Add a one-time afterEach hook to + // mount the app wait for redirect and route gets resolved + const unregisterHook = router.afterEach((to, from) => { + unregisterHook() + clientFirstMount() + }) + + // Push the path and let route to be resolved + router.push(path, undefined, (err) => { + if (err) { + errorHandler(err) + } + }) + }, + { aborted: false }) +} diff --git a/examples/nuxt-example/.nuxt/components/index.js b/examples/nuxt-example/.nuxt/components/index.js new file mode 100644 index 00000000..c2ce4a94 --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/index.js @@ -0,0 +1,34 @@ +export { default as NavBar } from '../..\\components\\NavBar.vue' +export { default as NuxtLogo } from '../..\\components\\NuxtLogo.vue' +export { default as Tutorial } from '../..\\components\\Tutorial.vue' + +// nuxt/nuxt.js#8607 +function wrapFunctional(options) { + if (!options || !options.functional) { + return options + } + + const propKeys = Array.isArray(options.props) ? options.props : Object.keys(options.props || {}) + + return { + render(h) { + const attrs = {} + const props = {} + + for (const key in this.$attrs) { + if (propKeys.includes(key)) { + props[key] = this.$attrs[key] + } else { + attrs[key] = this.$attrs[key] + } + } + + return h(options, { + on: this.$listeners, + attrs, + props, + scopedSlots: this.$scopedSlots, + }, this.$slots.default) + } + } +} diff --git a/examples/nuxt-example/.nuxt/components/nuxt-build-indicator.vue b/examples/nuxt-example/.nuxt/components/nuxt-build-indicator.vue new file mode 100644 index 00000000..913f5448 --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/nuxt-build-indicator.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/examples/nuxt-example/.nuxt/components/nuxt-child.js b/examples/nuxt-example/.nuxt/components/nuxt-child.js new file mode 100644 index 00000000..9db3ee27 --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/nuxt-child.js @@ -0,0 +1,121 @@ +export default { + name: 'NuxtChild', + functional: true, + props: { + nuxtChildKey: { + type: String, + default: '' + }, + keepAlive: Boolean, + keepAliveProps: { + type: Object, + default: undefined + } + }, + render (_, { parent, data, props }) { + const h = parent.$createElement + + data.nuxtChild = true + const _parent = parent + const transitions = parent.$nuxt.nuxt.transitions + const defaultTransition = parent.$nuxt.nuxt.defaultTransition + + let depth = 0 + while (parent) { + if (parent.$vnode && parent.$vnode.data.nuxtChild) { + depth++ + } + parent = parent.$parent + } + data.nuxtChildDepth = depth + const transition = transitions[depth] || defaultTransition + const transitionProps = {} + transitionsKeys.forEach((key) => { + if (typeof transition[key] !== 'undefined') { + transitionProps[key] = transition[key] + } + }) + + const listeners = {} + listenersKeys.forEach((key) => { + if (typeof transition[key] === 'function') { + listeners[key] = transition[key].bind(_parent) + } + }) + if (process.client) { + // Add triggerScroll event on beforeEnter (fix #1376) + const beforeEnter = listeners.beforeEnter + listeners.beforeEnter = (el) => { + // Ensure to trigger scroll event after calling scrollBehavior + window.$nuxt.$nextTick(() => { + window.$nuxt.$emit('triggerScroll') + }) + if (beforeEnter) { + return beforeEnter.call(_parent, el) + } + } + } + + // make sure that leave is called asynchronous (fix #5703) + if (transition.css === false) { + const leave = listeners.leave + + // only add leave listener when user didnt provide one + // or when it misses the done argument + if (!leave || leave.length < 2) { + listeners.leave = (el, done) => { + if (leave) { + leave.call(_parent, el) + } + + _parent.$nextTick(done) + } + } + } + + let routerView = h('routerView', data) + + if (props.keepAlive) { + routerView = h('keep-alive', { props: props.keepAliveProps }, [routerView]) + } + + return h('transition', { + props: transitionProps, + on: listeners + }, [routerView]) + } +} + +const transitionsKeys = [ + 'name', + 'mode', + 'appear', + 'css', + 'type', + 'duration', + 'enterClass', + 'leaveClass', + 'appearClass', + 'enterActiveClass', + 'enterActiveClass', + 'leaveActiveClass', + 'appearActiveClass', + 'enterToClass', + 'leaveToClass', + 'appearToClass' +] + +const listenersKeys = [ + 'beforeEnter', + 'enter', + 'afterEnter', + 'enterCancelled', + 'beforeLeave', + 'leave', + 'afterLeave', + 'leaveCancelled', + 'beforeAppear', + 'appear', + 'afterAppear', + 'appearCancelled' +] diff --git a/examples/nuxt-example/.nuxt/components/nuxt-error.vue b/examples/nuxt-example/.nuxt/components/nuxt-error.vue new file mode 100644 index 00000000..e71f7d01 --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/nuxt-error.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/examples/nuxt-example/.nuxt/components/nuxt-link.client.js b/examples/nuxt-example/.nuxt/components/nuxt-link.client.js new file mode 100644 index 00000000..1477cfd0 --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/nuxt-link.client.js @@ -0,0 +1,98 @@ +import Vue from 'vue' + +const requestIdleCallback = window.requestIdleCallback || + function (cb) { + const start = Date.now() + return setTimeout(function () { + cb({ + didTimeout: false, + timeRemaining: () => Math.max(0, 50 - (Date.now() - start)) + }) + }, 1) + } + +const cancelIdleCallback = window.cancelIdleCallback || function (id) { + clearTimeout(id) +} + +const observer = window.IntersectionObserver && new window.IntersectionObserver((entries) => { + entries.forEach(({ intersectionRatio, target: link }) => { + if (intersectionRatio <= 0 || !link.__prefetch) { + return + } + link.__prefetch() + }) +}) + +export default { + name: 'NuxtLink', + extends: Vue.component('RouterLink'), + props: { + prefetch: { + type: Boolean, + default: true + }, + noPrefetch: { + type: Boolean, + default: false + } + }, + mounted () { + if (this.prefetch && !this.noPrefetch) { + this.handleId = requestIdleCallback(this.observe, { timeout: 2e3 }) + } + }, + beforeDestroy () { + cancelIdleCallback(this.handleId) + + if (this.__observed) { + observer.unobserve(this.$el) + delete this.$el.__prefetch + } + }, + methods: { + observe () { + // If no IntersectionObserver, avoid prefetching + if (!observer) { + return + } + // Add to observer + if (this.shouldPrefetch()) { + this.$el.__prefetch = this.prefetchLink.bind(this) + observer.observe(this.$el) + this.__observed = true + } + }, + shouldPrefetch () { + return this.getPrefetchComponents().length > 0 + }, + canPrefetch () { + const conn = navigator.connection + const hasBadConnection = this.$nuxt.isOffline || (conn && ((conn.effectiveType || '').includes('2g') || conn.saveData)) + + return !hasBadConnection + }, + getPrefetchComponents () { + const ref = this.$router.resolve(this.to, this.$route, this.append) + const Components = ref.resolved.matched.map(r => r.components.default) + + return Components.filter(Component => typeof Component === 'function' && !Component.options && !Component.__prefetched) + }, + prefetchLink () { + if (!this.canPrefetch()) { + return + } + // Stop observing this link (in case of internet connection changes) + observer.unobserve(this.$el) + const Components = this.getPrefetchComponents() + + for (const Component of Components) { + const componentOrPromise = Component() + if (componentOrPromise instanceof Promise) { + componentOrPromise.catch(() => {}) + } + Component.__prefetched = true + } + } + } +} diff --git a/examples/nuxt-example/.nuxt/components/nuxt-link.server.js b/examples/nuxt-example/.nuxt/components/nuxt-link.server.js new file mode 100644 index 00000000..f1230908 --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/nuxt-link.server.js @@ -0,0 +1,16 @@ +import Vue from 'vue' + +export default { + name: 'NuxtLink', + extends: Vue.component('RouterLink'), + props: { + prefetch: { + type: Boolean, + default: true + }, + noPrefetch: { + type: Boolean, + default: false + } + } +} diff --git a/examples/nuxt-example/.nuxt/components/nuxt-loading.vue b/examples/nuxt-example/.nuxt/components/nuxt-loading.vue new file mode 100644 index 00000000..19e6311b --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/nuxt-loading.vue @@ -0,0 +1,178 @@ + + + diff --git a/examples/nuxt-example/.nuxt/components/nuxt.js b/examples/nuxt-example/.nuxt/components/nuxt.js new file mode 100644 index 00000000..e401ed3d --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/nuxt.js @@ -0,0 +1,102 @@ +import Vue from 'vue' +import { compile } from '../utils' + +import NuxtError from './nuxt-error.vue' + +import NuxtChild from './nuxt-child' + +export default { + name: 'Nuxt', + components: { + NuxtChild, + NuxtError + }, + props: { + nuxtChildKey: { + type: String, + default: undefined + }, + keepAlive: Boolean, + keepAliveProps: { + type: Object, + default: undefined + }, + name: { + type: String, + default: 'default' + } + }, + errorCaptured (error) { + // if we receive and error while showing the NuxtError component + // capture the error and force an immediate update so we re-render + // without the NuxtError component + if (this.displayingNuxtError) { + this.errorFromNuxtError = error + this.$forceUpdate() + } + }, + computed: { + routerViewKey () { + // If nuxtChildKey prop is given or current route has children + if (typeof this.nuxtChildKey !== 'undefined' || this.$route.matched.length > 1) { + return this.nuxtChildKey || compile(this.$route.matched[0].path)(this.$route.params) + } + + const [matchedRoute] = this.$route.matched + + if (!matchedRoute) { + return this.$route.path + } + + const Component = matchedRoute.components.default + + if (Component && Component.options) { + const { options } = Component + + if (options.key) { + return (typeof options.key === 'function' ? options.key(this.$route) : options.key) + } + } + + const strict = /\/$/.test(matchedRoute.path) + return strict ? this.$route.path : this.$route.path.replace(/\/$/, '') + } + }, + beforeCreate () { + Vue.util.defineReactive(this, 'nuxt', this.$root.$options.nuxt) + }, + render (h) { + // if there is no error or + // error page has not been loaded yet on client + if (!this.nuxt.err || (process.client && !this.nuxt.errPageReady)) { + // Directly return nuxt child + return h('NuxtChild', { + key: this.routerViewKey, + props: this.$props + }) + } + + // if an error occurred within NuxtError show a simple + // error message instead to prevent looping + if (this.errorFromNuxtError) { + this.$nextTick(() => (this.errorFromNuxtError = false)) + + return h('div', {}, [ + h('h2', 'An error occurred while showing the error page'), + h('p', 'Unfortunately an error occurred and while showing the error page another error occurred'), + h('p', `Error details: ${this.errorFromNuxtError.toString()}`), + h('nuxt-link', { props: { to: '/' } }, 'Go back to home') + ]) + } + + // track if we are showing the NuxtError component + this.displayingNuxtError = true + this.$nextTick(() => (this.displayingNuxtError = false)) + + return h(NuxtError, { + props: { + error: this.nuxt.err + } + }) + } +} diff --git a/examples/nuxt-example/.nuxt/components/plugin.js b/examples/nuxt-example/.nuxt/components/plugin.js new file mode 100644 index 00000000..121bdcf1 --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/plugin.js @@ -0,0 +1,7 @@ +import Vue from 'vue' +import * as components from './index' + +for (const name in components) { + Vue.component(name, components[name]) + Vue.component('Lazy' + name, components[name]) +} diff --git a/examples/nuxt-example/.nuxt/components/readme.md b/examples/nuxt-example/.nuxt/components/readme.md new file mode 100644 index 00000000..8448575c --- /dev/null +++ b/examples/nuxt-example/.nuxt/components/readme.md @@ -0,0 +1,11 @@ +# Discovered Components + +This is an auto-generated list of components discovered by [nuxt/components](https://github.com/nuxt/components). + +You can directly use them in pages and other components without the need to import them. + +**Tip:** If a component is conditionally rendered with `v-if` and is big, it is better to use `Lazy` or `lazy-` prefix to lazy load. + +- `` | `` (components/NavBar.vue) +- `` | `` (components/NuxtLogo.vue) +- `` | `` (components/Tutorial.vue) diff --git a/examples/nuxt-example/.nuxt/empty.js b/examples/nuxt-example/.nuxt/empty.js new file mode 100644 index 00000000..a3ac0d84 --- /dev/null +++ b/examples/nuxt-example/.nuxt/empty.js @@ -0,0 +1 @@ +// This file is intentionally left empty for noop aliases diff --git a/examples/nuxt-example/.nuxt/index.js b/examples/nuxt-example/.nuxt/index.js new file mode 100644 index 00000000..e102393e --- /dev/null +++ b/examples/nuxt-example/.nuxt/index.js @@ -0,0 +1,228 @@ +import Vue from 'vue' + +import Meta from 'vue-meta' +import ClientOnly from 'vue-client-only' +import NoSsr from 'vue-no-ssr' +import { createRouter } from './router.js' +import NuxtChild from './components/nuxt-child.js' +import NuxtError from './components/nuxt-error.vue' +import Nuxt from './components/nuxt.js' +import App from './App.js' +import { setContext, getLocation, getRouteData, normalizeError } from './utils' + +/* Plugins */ + +import nuxt_plugin_plugin_9bcb59fa from 'nuxt_plugin_plugin_9bcb59fa' // Source: .\\components\\plugin.js (mode: 'all') + +// Component: +Vue.component(ClientOnly.name, ClientOnly) + +// TODO: Remove in Nuxt 3: +Vue.component(NoSsr.name, { + ...NoSsr, + render (h, ctx) { + if (process.client && !NoSsr._warned) { + NoSsr._warned = true + + console.warn(' has been deprecated and will be removed in Nuxt 3, please use instead') + } + return NoSsr.render(h, ctx) + } +}) + +// Component: +Vue.component(NuxtChild.name, NuxtChild) +Vue.component('NChild', NuxtChild) + +// Component NuxtLink is imported in server.js or client.js + +// Component: +Vue.component(Nuxt.name, Nuxt) + +Object.defineProperty(Vue.prototype, '$nuxt', { + get() { + const globalNuxt = this.$root ? this.$root.$options.$nuxt : null + if (process.client && !globalNuxt && typeof window !== 'undefined') { + return window.$nuxt + } + return globalNuxt + }, + configurable: true +}) + +Vue.use(Meta, {"keyName":"head","attribute":"data-n-head","ssrAttribute":"data-n-head-ssr","tagIDKeyName":"hid"}) + +const defaultTransition = {"name":"page","mode":"out-in","appear":false,"appearClass":"appear","appearActiveClass":"appear-active","appearToClass":"appear-to"} + +async function createApp(ssrContext, config = {}) { + const store = null + const router = await createRouter(ssrContext, config, { store }) + + // Create Root instance + + // here we inject the router and store to all child components, + // making them available everywhere as `this.$router` and `this.$store`. + const app = { + head: {"title":"nuxt-app-example","htmlAttrs":{"lang":"en"},"meta":[{"charset":"utf-8"},{"name":"viewport","content":"width=device-width, initial-scale=1"},{"hid":"description","name":"description","content":""},{"name":"format-detection","content":"telephone=no"}],"link":[{"rel":"icon","type":"image\u002Fx-icon","href":"\u002Ffavicon.ico"}],"style":[],"script":[]}, + + router, + nuxt: { + defaultTransition, + transitions: [defaultTransition], + setTransitions (transitions) { + if (!Array.isArray(transitions)) { + transitions = [transitions] + } + transitions = transitions.map((transition) => { + if (!transition) { + transition = defaultTransition + } else if (typeof transition === 'string') { + transition = Object.assign({}, defaultTransition, { name: transition }) + } else { + transition = Object.assign({}, defaultTransition, transition) + } + return transition + }) + this.$options.nuxt.transitions = transitions + return transitions + }, + + err: null, + errPageReady: false, + dateErr: null, + error (err) { + err = err || null + app.context._errored = Boolean(err) + err = err ? normalizeError(err) : null + let nuxt = app.nuxt // to work with @vue/composition-api, see https://github.com/nuxt/nuxt.js/issues/6517#issuecomment-573280207 + if (this) { + nuxt = this.nuxt || this.$options.nuxt + } + nuxt.dateErr = Date.now() + nuxt.err = err + nuxt.errPageReady = false + // Used in src/server.js + if (ssrContext) { + ssrContext.nuxt.error = err + } + return err + } + }, + ...App + } + + const next = ssrContext ? ssrContext.next : location => app.router.push(location) + // Resolve route + let route + if (ssrContext) { + route = router.resolve(ssrContext.url).route + } else { + const path = getLocation(router.options.base, router.options.mode) + route = router.resolve(path).route + } + + // Set context to app.context + await setContext(app, { + route, + next, + error: app.nuxt.error.bind(app), + payload: ssrContext ? ssrContext.payload : undefined, + req: ssrContext ? ssrContext.req : undefined, + res: ssrContext ? ssrContext.res : undefined, + beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined, + beforeSerializeFns: ssrContext ? ssrContext.beforeSerializeFns : undefined, + ssrContext + }) + + function inject(key, value) { + if (!key) { + throw new Error('inject(key, value) has no key provided') + } + if (value === undefined) { + throw new Error(`inject('${key}', value) has no value provided`) + } + + key = '$' + key + // Add into app + app[key] = value + // Add into context + if (!app.context[key]) { + app.context[key] = value + } + + // Check if plugin not already installed + const installKey = '__nuxt_' + key + '_installed__' + if (Vue[installKey]) { + return + } + Vue[installKey] = true + // Call Vue.use() to install the plugin into vm + Vue.use(() => { + if (!Object.prototype.hasOwnProperty.call(Vue.prototype, key)) { + Object.defineProperty(Vue.prototype, key, { + get () { + return this.$root.$options[key] + } + }) + } + }) + } + + // Inject runtime config as $config + inject('config', config) + + // Add enablePreview(previewData = {}) in context for plugins + if (process.static && process.client) { + app.context.enablePreview = function (previewData = {}) { + app.previewData = Object.assign({}, previewData) + inject('preview', previewData) + } + } + // Plugin execution + + if (typeof nuxt_plugin_plugin_9bcb59fa === 'function') { + await nuxt_plugin_plugin_9bcb59fa(app.context, inject) + } + + // Lock enablePreview in context + if (process.static && process.client) { + app.context.enablePreview = function () { + console.warn('You cannot call enablePreview() outside a plugin.') + } + } + + // Wait for async component to be resolved first + await new Promise((resolve, reject) => { + // Ignore 404s rather than blindly replacing URL in browser + if (process.client) { + const { route } = router.resolve(app.context.route.fullPath) + if (!route.matched.length) { + return resolve() + } + } + router.replace(app.context.route.fullPath, resolve, (err) => { + // https://github.com/vuejs/vue-router/blob/v3.4.3/src/util/errors.js + if (!err._isRouter) return reject(err) + if (err.type !== 2 /* NavigationFailureType.redirected */) return resolve() + + // navigated to a different route in router guard + const unregister = router.afterEach(async (to, from) => { + if (process.server && ssrContext && ssrContext.url) { + ssrContext.url = to.fullPath + } + app.context.route = await getRouteData(to) + app.context.params = to.params || {} + app.context.query = to.query || {} + unregister() + resolve() + }) + }) + }) + + return { + app, + router + } +} + +export { createApp, NuxtError } diff --git a/examples/nuxt-example/.nuxt/jsonp.js b/examples/nuxt-example/.nuxt/jsonp.js new file mode 100644 index 00000000..702adf21 --- /dev/null +++ b/examples/nuxt-example/.nuxt/jsonp.js @@ -0,0 +1,82 @@ +const chunks = {} // chunkId => exports +const chunksInstalling = {} // chunkId => Promise +const failedChunks = {} + +function importChunk(chunkId, src) { + // Already installed + if (chunks[chunkId]) { + return Promise.resolve(chunks[chunkId]) + } + + // Failed loading + if (failedChunks[chunkId]) { + return Promise.reject(failedChunks[chunkId]) + } + + // Installing + if (chunksInstalling[chunkId]) { + return chunksInstalling[chunkId] + } + + // Set a promise in chunk cache + let resolve, reject + const promise = chunksInstalling[chunkId] = new Promise((_resolve, _reject) => { + resolve = _resolve + reject = _reject + }) + + // Clear chunk data from cache + delete chunks[chunkId] + + // Start chunk loading + const script = document.createElement('script') + script.charset = 'utf-8' + script.timeout = 120 + script.src = src + let timeout + + // Create error before stack unwound to get useful stacktrace later + const error = new Error() + + // Complete handlers + const onScriptComplete = script.onerror = script.onload = (event) => { + // Cleanups + clearTimeout(timeout) + delete chunksInstalling[chunkId] + + // Avoid mem leaks in IE + script.onerror = script.onload = null + + // Verify chunk is loaded + if (chunks[chunkId]) { + return resolve(chunks[chunkId]) + } + + // Something bad happened + const errorType = event && (event.type === 'load' ? 'missing' : event.type) + const realSrc = event && event.target && event.target.src + error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')' + error.name = 'ChunkLoadError' + error.type = errorType + error.request = realSrc + failedChunks[chunkId] = error + reject(error) + } + + // Timeout + timeout = setTimeout(() => { + onScriptComplete({ type: 'timeout', target: script }) + }, 120000) + + // Append script + document.head.appendChild(script) + + // Return promise + return promise +} + +export function installJsonp() { + window.__NUXT_JSONP__ = function (chunkId, exports) { chunks[chunkId] = exports } + window.__NUXT_JSONP_CACHE__ = chunks + window.__NUXT_IMPORT__ = importChunk +} diff --git a/examples/nuxt-example/.nuxt/loading.html b/examples/nuxt-example/.nuxt/loading.html new file mode 100644 index 00000000..a6dcd1b5 --- /dev/null +++ b/examples/nuxt-example/.nuxt/loading.html @@ -0,0 +1,110 @@ + + + + +
Loading...
+ + diff --git a/examples/nuxt-example/.nuxt/middleware.js b/examples/nuxt-example/.nuxt/middleware.js new file mode 100644 index 00000000..343ef954 --- /dev/null +++ b/examples/nuxt-example/.nuxt/middleware.js @@ -0,0 +1,3 @@ +const middleware = {} + +export default middleware diff --git a/examples/nuxt-example/.nuxt/mixins/fetch.client.js b/examples/nuxt-example/.nuxt/mixins/fetch.client.js new file mode 100644 index 00000000..017e559e --- /dev/null +++ b/examples/nuxt-example/.nuxt/mixins/fetch.client.js @@ -0,0 +1,90 @@ +import Vue from 'vue' +import { hasFetch, normalizeError, addLifecycleHook, createGetCounter } from '../utils' + +const isSsrHydration = (vm) => vm.$vnode && vm.$vnode.elm && vm.$vnode.elm.dataset && vm.$vnode.elm.dataset.fetchKey +const nuxtState = window.__NUXT__ + +export default { + beforeCreate () { + if (!hasFetch(this)) { + return + } + + this._fetchDelay = typeof this.$options.fetchDelay === 'number' ? this.$options.fetchDelay : 200 + + Vue.util.defineReactive(this, '$fetchState', { + pending: false, + error: null, + timestamp: Date.now() + }) + + this.$fetch = $fetch.bind(this) + addLifecycleHook(this, 'created', created) + addLifecycleHook(this, 'beforeMount', beforeMount) + } +} + +function beforeMount() { + if (!this._hydrated) { + return this.$fetch() + } +} + +function created() { + if (!isSsrHydration(this)) { + return + } + + // Hydrate component + this._hydrated = true + this._fetchKey = this.$vnode.elm.dataset.fetchKey + const data = nuxtState.fetch[this._fetchKey] + + // If fetch error + if (data && data._error) { + this.$fetchState.error = data._error + return + } + + // Merge data + for (const key in data) { + Vue.set(this.$data, key, data[key]) + } +} + +function $fetch() { + if (!this._fetchPromise) { + this._fetchPromise = $_fetch.call(this) + .then(() => { delete this._fetchPromise }) + } + return this._fetchPromise +} + +async function $_fetch() { + this.$nuxt.nbFetching++ + this.$fetchState.pending = true + this.$fetchState.error = null + this._hydrated = false + let error = null + const startTime = Date.now() + + try { + await this.$options.fetch.call(this) + } catch (err) { + if (process.dev) { + console.error('Error in fetch():', err) + } + error = normalizeError(err) + } + + const delayLeft = this._fetchDelay - (Date.now() - startTime) + if (delayLeft > 0) { + await new Promise(resolve => setTimeout(resolve, delayLeft)) + } + + this.$fetchState.error = error + this.$fetchState.pending = false + this.$fetchState.timestamp = Date.now() + + this.$nextTick(() => this.$nuxt.nbFetching--) +} diff --git a/examples/nuxt-example/.nuxt/mixins/fetch.server.js b/examples/nuxt-example/.nuxt/mixins/fetch.server.js new file mode 100644 index 00000000..24a00686 --- /dev/null +++ b/examples/nuxt-example/.nuxt/mixins/fetch.server.js @@ -0,0 +1,69 @@ +import Vue from 'vue' +import { hasFetch, normalizeError, addLifecycleHook, purifyData, createGetCounter } from '../utils' + +async function serverPrefetch() { + if (!this._fetchOnServer) { + return + } + + // Call and await on $fetch + try { + await this.$options.fetch.call(this) + } catch (err) { + if (process.dev) { + console.error('Error in fetch():', err) + } + this.$fetchState.error = normalizeError(err) + } + this.$fetchState.pending = false + + // Define an ssrKey for hydration + this._fetchKey = this._fetchKey || this.$ssrContext.fetchCounters['']++ + + // Add data-fetch-key on parent element of Component + const attrs = this.$vnode.data.attrs = this.$vnode.data.attrs || {} + attrs['data-fetch-key'] = this._fetchKey + + // Add to ssrContext for window.__NUXT__.fetch + + if (this.$ssrContext.nuxt.fetch[this._fetchKey] !== undefined) { + console.warn(`Duplicate fetch key detected (${this._fetchKey}). This may lead to unexpected results.`) + } + + this.$ssrContext.nuxt.fetch[this._fetchKey] = + this.$fetchState.error ? { _error: this.$fetchState.error } : purifyData(this._data) +} + +export default { + created() { + if (!hasFetch(this)) { + return + } + + if (typeof this.$options.fetchOnServer === 'function') { + this._fetchOnServer = this.$options.fetchOnServer.call(this) !== false + } else { + this._fetchOnServer = this.$options.fetchOnServer !== false + } + + const defaultKey = this.$options._scopeId || this.$options.name || '' + const getCounter = createGetCounter(this.$ssrContext.fetchCounters, defaultKey) + + if (typeof this.$options.fetchKey === 'function') { + this._fetchKey = this.$options.fetchKey.call(this, getCounter) + } else { + const key = 'string' === typeof this.$options.fetchKey ? this.$options.fetchKey : defaultKey + this._fetchKey = key ? key + ':' + getCounter(key) : String(getCounter(key)) + } + + // Added for remove vue undefined warning while ssr + this.$fetch = () => {} // issue #8043 + Vue.util.defineReactive(this, '$fetchState', { + pending: true, + error: null, + timestamp: Date.now() + }) + + addLifecycleHook(this, 'serverPrefetch', serverPrefetch) + } +} diff --git a/examples/nuxt-example/.nuxt/router.js b/examples/nuxt-example/.nuxt/router.js new file mode 100644 index 00000000..142455ca --- /dev/null +++ b/examples/nuxt-example/.nuxt/router.js @@ -0,0 +1,53 @@ +import Vue from 'vue' +import Router from 'vue-router' +import { normalizeURL, decode } from 'ufo' +import { interopDefault } from './utils' +import scrollBehavior from './router.scrollBehavior.js' + +const _19757575 = () => interopDefault(import('..\\pages\\about.vue' /* webpackChunkName: "pages/about" */)) +const _392d503a = () => interopDefault(import('..\\pages\\index.vue' /* webpackChunkName: "pages/index" */)) + +const emptyFn = () => {} + +Vue.use(Router) + +export const routerOptions = { + mode: 'history', + base: '/', + linkActiveClass: 'nuxt-link-active', + linkExactActiveClass: 'nuxt-link-exact-active', + scrollBehavior, + + routes: [{ + path: "/about", + component: _19757575, + name: "about" + }, { + path: "/", + component: _392d503a, + name: "index" + }], + + fallback: false +} + +export function createRouter (ssrContext, config) { + const base = (config._app && config._app.basePath) || routerOptions.base + const router = new Router({ ...routerOptions, base }) + + // TODO: remove in Nuxt 3 + const originalPush = router.push + router.push = function push (location, onComplete = emptyFn, onAbort) { + return originalPush.call(this, location, onComplete, onAbort) + } + + const resolve = router.resolve.bind(router) + router.resolve = (to, current, append) => { + if (typeof to === 'string') { + to = normalizeURL(to) + } + return resolve(to, current, append) + } + + return router +} diff --git a/examples/nuxt-example/.nuxt/router.scrollBehavior.js b/examples/nuxt-example/.nuxt/router.scrollBehavior.js new file mode 100644 index 00000000..fd193781 --- /dev/null +++ b/examples/nuxt-example/.nuxt/router.scrollBehavior.js @@ -0,0 +1,82 @@ +import { getMatchedComponents, setScrollRestoration } from './utils' + +if (process.client) { + if ('scrollRestoration' in window.history) { + setScrollRestoration('manual') + + // reset scrollRestoration to auto when leaving page, allowing page reload + // and back-navigation from other pages to use the browser to restore the + // scrolling position. + window.addEventListener('beforeunload', () => { + setScrollRestoration('auto') + }) + + // Setting scrollRestoration to manual again when returning to this page. + window.addEventListener('load', () => { + setScrollRestoration('manual') + }) + } +} + +function shouldScrollToTop(route) { + const Pages = getMatchedComponents(route) + if (Pages.length === 1) { + const { options = {} } = Pages[0] + return options.scrollToTop !== false + } + return Pages.some(({ options }) => options && options.scrollToTop) +} + +export default function (to, from, savedPosition) { + // If the returned position is falsy or an empty object, will retain current scroll position + let position = false + const isRouteChanged = to !== from + + // savedPosition is only available for popstate navigations (back button) + if (savedPosition) { + position = savedPosition + } else if (isRouteChanged && shouldScrollToTop(to)) { + position = { x: 0, y: 0 } + } + + const nuxt = window.$nuxt + + if ( + // Initial load (vuejs/vue-router#3199) + !isRouteChanged || + // Route hash changes + (to.path === from.path && to.hash !== from.hash) + ) { + nuxt.$nextTick(() => nuxt.$emit('triggerScroll')) + } + + return new Promise((resolve) => { + // wait for the out transition to complete (if necessary) + nuxt.$once('triggerScroll', () => { + // coords will be used if no selector is provided, + // or if the selector didn't match any element. + if (to.hash) { + let hash = to.hash + // CSS.escape() is not supported with IE and Edge. + if (typeof window.CSS !== 'undefined' && typeof window.CSS.escape !== 'undefined') { + hash = '#' + window.CSS.escape(hash.substr(1)) + } + try { + const el = document.querySelector(hash) + if (el) { + // scroll to anchor by returning the selector + position = { selector: hash } + // Respect any scroll-margin-top set in CSS when scrolling to anchor + const y = Number(getComputedStyle(el)['scroll-margin-top']?.replace('px', '')) + if (y) { + position.offset = { y } + } + } + } catch (e) { + console.warn('Failed to save scroll position. Please add CSS.escape() polyfill (https://github.com/mathiasbynens/CSS.escape).') + } + } + resolve(position) + }) + }) +} diff --git a/examples/nuxt-example/.nuxt/routes.json b/examples/nuxt-example/.nuxt/routes.json new file mode 100644 index 00000000..bd5321ec --- /dev/null +++ b/examples/nuxt-example/.nuxt/routes.json @@ -0,0 +1,16 @@ +[ + { + "name": "about", + "path": "/about", + "component": "C:\\\\Users\\\\linglingye\\\\JavaScript\\\\nuxt-app-example\\\\pages\\\\about.vue", + "chunkName": "pages/about", + "_name": "_19757575" + }, + { + "name": "index", + "path": "/", + "component": "C:\\\\Users\\\\linglingye\\\\JavaScript\\\\nuxt-app-example\\\\pages\\\\index.vue", + "chunkName": "pages/index", + "_name": "_392d503a" + } +] diff --git a/examples/nuxt-example/.nuxt/server.js b/examples/nuxt-example/.nuxt/server.js new file mode 100644 index 00000000..9a3f24da --- /dev/null +++ b/examples/nuxt-example/.nuxt/server.js @@ -0,0 +1,296 @@ +import Vue from 'vue' +import { joinURL, normalizeURL, withQuery } from 'ufo' +import fetch from 'node-fetch-native' +import middleware from './middleware.js' +import { + applyAsyncData, + middlewareSeries, + sanitizeComponent, + getMatchedComponents, + promisify +} from './utils.js' + import fetchMixin from './mixins/fetch.server' +import { createApp, NuxtError } from './index.js' +import NuxtLink from './components/nuxt-link.server.js' // should be included after ./index.js + + // Update serverPrefetch strategy + Vue.config.optionMergeStrategies.serverPrefetch = Vue.config.optionMergeStrategies.created + + // Fetch mixin + if (!Vue.__nuxt__fetch__mixin__) { + Vue.mixin(fetchMixin) + Vue.__nuxt__fetch__mixin__ = true + } + +if (!Vue.__original_use__) { + Vue.__original_use__ = Vue.use + Vue.__install_times__ = 0 + Vue.use = function (plugin, ...args) { + plugin.__nuxt_external_installed__ = Vue._installedPlugins.includes(plugin) + return Vue.__original_use__(plugin, ...args) + } + } + if (Vue.__install_times__ === 2) { + Vue.__install_times__ = 0 + Vue._installedPlugins = Vue._installedPlugins.filter(plugin => { + return plugin.__nuxt_external_installed__ === true + }) + } + Vue.__install_times__++ + + // Component: + Vue.component(NuxtLink.name, NuxtLink) + Vue.component('NLink', NuxtLink) + +if (!global.fetch) { global.fetch = fetch } + +const noopApp = () => new Vue({ render: h => h('div', { domProps: { id: '__nuxt' } }) }) + +const createNext = ssrContext => (opts) => { + // If static target, render on client-side + ssrContext.redirected = opts + if (ssrContext.target === 'static' || !ssrContext.res) { + ssrContext.nuxt.serverRendered = false + return + } + let fullPath = withQuery(opts.path, opts.query) + const $config = ssrContext.nuxt.config || {} + const routerBase = ($config._app && $config._app.basePath) || '/' + if (!fullPath.startsWith('http') && (routerBase !== '/' && !fullPath.startsWith(routerBase))) { + fullPath = joinURL(routerBase, fullPath) + } + // Avoid loop redirect + if (decodeURI(fullPath) === decodeURI(ssrContext.url)) { + ssrContext.redirected = false + return + } + ssrContext.res.writeHead(opts.status, { + Location: normalizeURL(fullPath) + }) + ssrContext.res.end() +} + +// This exported function will be called by `bundleRenderer`. +// This is where we perform data-prefetching to determine the +// state of our application before actually rendering it. +// Since data fetching is async, this function is expected to +// return a Promise that resolves to the app instance. +export default async (ssrContext) => { + // Create ssrContext.next for simulate next() of beforeEach() when wanted to redirect + ssrContext.redirected = false + ssrContext.next = createNext(ssrContext) + // Used for beforeNuxtRender({ Components, nuxtState }) + ssrContext.beforeRenderFns = [] + // for beforeSerialize(nuxtState) + ssrContext.beforeSerializeFns = [] + // Nuxt object (window.{{globals.context}}, defaults to window.__NUXT__) + ssrContext.nuxt = { layout: 'default', data: [], fetch: { }, error: null , serverRendered: true, routePath: '' +} + + ssrContext.fetchCounters = { } + + // Remove query from url is static target + + // Public runtime config + ssrContext.nuxt.config = ssrContext.runtimeConfig.public +if (ssrContext.nuxt.config._app) { + __webpack_public_path__ = joinURL(ssrContext.nuxt.config._app.cdnURL, ssrContext.nuxt.config._app.assetsPath) +} +// Create the app definition and the instance (created for each request) +const { app, router } = await createApp(ssrContext, ssrContext.runtimeConfig.private) +const _app = new Vue(app) +// Add ssr route path to nuxt context so we can account for page navigation between ssr and csr +ssrContext.nuxt.routePath = app.context.route.path + + // Add meta infos (used in renderer.js) + ssrContext.meta = _app.$meta() + + // Keep asyncData for each matched component in ssrContext (used in app/utils.js via this.$ssrContext) + ssrContext.asyncData = { } + + const beforeRender = async () => { + // Call beforeNuxtRender() methods + await Promise.all(ssrContext.beforeRenderFns.map(fn => promisify(fn, { Components, nuxtState: ssrContext.nuxt }))) + + ssrContext.rendered = () => { + // Call beforeSerialize() hooks + ssrContext.beforeSerializeFns.forEach(fn => fn(ssrContext.nuxt)) + } +} + +const renderErrorPage = async () => { + // Don't server-render the page in static target + if (ssrContext.target === 'static') { + ssrContext.nuxt.serverRendered = false + } + + // Load layout for error page + const layout = (NuxtError.options || NuxtError).layout + const errLayout = typeof layout === 'function' ? layout.call(NuxtError, app.context) : layout + ssrContext.nuxt.layout = errLayout || 'default' + await _app.loadLayout(errLayout) + _app.setLayout(errLayout) + + await beforeRender() + return _app +} +const render404Page = () => { + app.context.error({ statusCode: 404, path: ssrContext.url, message: 'This page could not be found' }) + return renderErrorPage() +} + + const s = Date.now() + + // Components are already resolved by setContext -> getRouteData (app/utils.js) + const Components = getMatchedComponents(app.context.route) + + /* + ** Call global middleware (nuxt.config.js) + */ + let midd = [] + midd = midd.map((name) => { + if (typeof name === 'function') { + return name + } + if (typeof middleware[name] !== 'function') { + app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) + } + return middleware[name] + }) + await middlewareSeries(midd, app.context) + // ...If there is a redirect or an error, stop the process + if (ssrContext.redirected) { + return noopApp() + } + if (ssrContext.nuxt.error) { + return renderErrorPage() + } + + /* + ** Set layout + */ + let layout = Components.length ? Components[0].options.layout : NuxtError.layout + if (typeof layout === 'function') { + layout = layout(app.context) + } + await _app.loadLayout(layout) + if (ssrContext.nuxt.error) { + return renderErrorPage() + } + layout = _app.setLayout(layout) + ssrContext.nuxt.layout = _app.layoutName + + /* + ** Call middleware (layout + pages) + */ + midd =[] + + layout = sanitizeComponent(layout) + if (layout.options.middleware) { + midd = midd.concat(layout.options.middleware) + } + + Components.forEach((Component) => { + if (Component.options.middleware) { + midd = midd.concat(Component.options.middleware) + } + }) + midd = midd.map((name) => { + if (typeof name === 'function') { + return name + } + if (typeof middleware[name] !== 'function') { + app.context.error({ statusCode: 500, message: 'Unknown middleware ' + name }) + } + return middleware[name] + }) + await middlewareSeries(midd, app.context) + // ...If there is a redirect or an error, stop the process + if (ssrContext.redirected) { + return noopApp() + } + if (ssrContext.nuxt.error) { + return renderErrorPage() + } + + /* + ** Call .validate() + */ + let isValid = true + try { + for (const Component of Components) { + if (typeof Component.options.validate !== 'function') { + continue + } + + isValid = await Component.options.validate(app.context) + + if (!isValid) { + break + } + } + } catch (validationError) { + // ...If .validate() threw an error + app.context.error({ + statusCode: validationError.statusCode || '500', + message: validationError.message + }) + return renderErrorPage() + } + + // ...If .validate() returned false + if (!isValid) { + // Render a 404 error page + return render404Page() + } + + // If no Components found, returns 404 + if (!Components.length) { + return render404Page() +} + + // Call asyncData & fetch hooks on components matched by the route. + const asyncDatas = await Promise.all(Components.map((Component) => { + const promises = [] + + // Call asyncData(context) + if (Component.options.asyncData && typeof Component.options.asyncData === 'function') { + const promise = promisify(Component.options.asyncData, app.context) + .then((asyncDataResult) => { + ssrContext.asyncData[Component.cid] = asyncDataResult + applyAsyncData(Component) + return asyncDataResult + }) + promises.push(promise) + } else { + promises.push(null) + } + + // Call fetch(context) + if (Component.options.fetch && Component.options.fetch.length) { + promises.push(Component.options.fetch(app.context)) + } else { + promises.push(null) + } + + return Promise.all(promises) +})) + + if (process.env.DEBUG && asyncDatas.length) console.debug('Data fetching ' + ssrContext.url + ': ' + (Date.now() - s) + 'ms') + + // datas are the first row of each + ssrContext.nuxt.data = asyncDatas.map(r => r[0] || {}) + + // ...If there is a redirect or an error, stop the process + if (ssrContext.redirected) { + return noopApp() +} +if (ssrContext.nuxt.error) { + return renderErrorPage() +} + +// Call beforeNuxtRender methods & add store state +await beforeRender() + +return _app +} diff --git a/examples/nuxt-example/.nuxt/utils.js b/examples/nuxt-example/.nuxt/utils.js new file mode 100644 index 00000000..4d271084 --- /dev/null +++ b/examples/nuxt-example/.nuxt/utils.js @@ -0,0 +1,637 @@ +import Vue from 'vue' +import { isSamePath as _isSamePath, joinURL, normalizeURL, withQuery, withoutTrailingSlash } from 'ufo' + +// window.{{globals.loadedCallback}} hook +// Useful for jsdom testing or plugins (https://github.com/tmpvar/jsdom#dealing-with-asynchronous-script-loading) +if (process.client) { + window.onNuxtReadyCbs = [] + window.onNuxtReady = (cb) => { + window.onNuxtReadyCbs.push(cb) + } +} + +export function createGetCounter (counterObject, defaultKey = '') { + return function getCounter (id = defaultKey) { + if (counterObject[id] === undefined) { + counterObject[id] = 0 + } + return counterObject[id]++ + } +} + +export function empty () {} + +export function globalHandleError (error) { + if (Vue.config.errorHandler) { + Vue.config.errorHandler(error) + } +} + +export function interopDefault (promise) { + return promise.then(m => m.default || m) +} + +export function hasFetch(vm) { + return vm.$options && typeof vm.$options.fetch === 'function' && !vm.$options.fetch.length +} +export function purifyData(data) { + if (process.env.NODE_ENV === 'production') { + return data + } + + return Object.entries(data).filter( + ([key, value]) => { + const valid = !(value instanceof Function) && !(value instanceof Promise) + if (!valid) { + console.warn(`${key} is not able to be stringified. This will break in a production environment.`) + } + return valid + } + ).reduce((obj, [key, value]) => { + obj[key] = value + return obj + }, {}) +} +export function getChildrenComponentInstancesUsingFetch(vm, instances = []) { + const children = vm.$children || [] + for (const child of children) { + if (child.$fetch) { + instances.push(child) + } + if (child.$children) { + getChildrenComponentInstancesUsingFetch(child, instances) + } + } + return instances +} + +export function applyAsyncData (Component, asyncData) { + if ( + // For SSR, we once all this function without second param to just apply asyncData + // Prevent doing this for each SSR request + !asyncData && Component.options.__hasNuxtData + ) { + return + } + + const ComponentData = Component.options._originDataFn || Component.options.data || function () { return {} } + Component.options._originDataFn = ComponentData + + Component.options.data = function () { + const data = ComponentData.call(this, this) + if (this.$ssrContext) { + asyncData = this.$ssrContext.asyncData[Component.cid] + } + return { ...data, ...asyncData } + } + + Component.options.__hasNuxtData = true + + if (Component._Ctor && Component._Ctor.options) { + Component._Ctor.options.data = Component.options.data + } +} + +export function sanitizeComponent (Component) { + // If Component already sanitized + if (Component.options && Component._Ctor === Component) { + return Component + } + if (!Component.options) { + Component = Vue.extend(Component) // fix issue #6 + Component._Ctor = Component + } else { + Component._Ctor = Component + Component.extendOptions = Component.options + } + // If no component name defined, set file path as name, (also fixes #5703) + if (!Component.options.name && Component.options.__file) { + Component.options.name = Component.options.__file + } + return Component +} + +export function getMatchedComponents (route, matches = false, prop = 'components') { + return Array.prototype.concat.apply([], route.matched.map((m, index) => { + return Object.keys(m[prop]).map((key) => { + matches && matches.push(index) + return m[prop][key] + }) + })) +} + +export function getMatchedComponentsInstances (route, matches = false) { + return getMatchedComponents(route, matches, 'instances') +} + +export function flatMapComponents (route, fn) { + return Array.prototype.concat.apply([], route.matched.map((m, index) => { + return Object.keys(m.components).reduce((promises, key) => { + if (m.components[key]) { + promises.push(fn(m.components[key], m.instances[key], m, key, index)) + } else { + delete m.components[key] + } + return promises + }, []) + })) +} + +export function resolveRouteComponents (route, fn) { + return Promise.all( + flatMapComponents(route, async (Component, instance, match, key) => { + // If component is a function, resolve it + if (typeof Component === 'function' && !Component.options) { + try { + Component = await Component() + } catch (error) { + // Handle webpack chunk loading errors + // This may be due to a new deployment or a network problem + if ( + error && + error.name === 'ChunkLoadError' && + typeof window !== 'undefined' && + window.sessionStorage + ) { + const timeNow = Date.now() + try { + const previousReloadTime = parseInt(window.sessionStorage.getItem('nuxt-reload')) + // check for previous reload time not to reload infinitely + if (!previousReloadTime || previousReloadTime + 60000 < timeNow) { + window.sessionStorage.setItem('nuxt-reload', timeNow) + window.location.reload(true /* skip cache */) + } + } catch { + // don't throw an error if we have issues reading sessionStorage + } + } + + throw error + } + } + match.components[key] = Component = sanitizeComponent(Component) + return typeof fn === 'function' ? fn(Component, instance, match, key) : Component + }) + ) +} + +export async function getRouteData (route) { + if (!route) { + return + } + // Make sure the components are resolved (code-splitting) + await resolveRouteComponents(route) + // Send back a copy of route with meta based on Component definition + return { + ...route, + meta: getMatchedComponents(route).map((Component, index) => { + return { ...Component.options.meta, ...(route.matched[index] || {}).meta } + }) + } +} + +export async function setContext (app, context) { + // If context not defined, create it + if (!app.context) { + app.context = { + isStatic: process.static, + isDev: true, + isHMR: false, + app, + + payload: context.payload, + error: context.error, + base: app.router.options.base, + env: {} + } + // Only set once + + if (context.req) { + app.context.req = context.req + } + if (context.res) { + app.context.res = context.res + } + + if (context.ssrContext) { + app.context.ssrContext = context.ssrContext + } + app.context.redirect = (status, path, query) => { + if (!status) { + return + } + app.context._redirected = true + // if only 1 or 2 arguments: redirect('/') or redirect('/', { foo: 'bar' }) + let pathType = typeof path + if (typeof status !== 'number' && (pathType === 'undefined' || pathType === 'object')) { + query = path || {} + path = status + pathType = typeof path + status = 302 + } + if (pathType === 'object') { + path = app.router.resolve(path).route.fullPath + } + // "/absolute/route", "./relative/route" or "../relative/route" + if (/(^[.]{1,2}\/)|(^\/(?!\/))/.test(path)) { + app.context.next({ + path, + query, + status + }) + } else { + path = withQuery(path, query) + if (process.server) { + app.context.next({ + path, + status + }) + } + if (process.client) { + // https://developer.mozilla.org/en-US/docs/Web/API/Location/assign + window.location.assign(path) + + // Throw a redirect error + throw new Error('ERR_REDIRECT') + } + } + } + if (process.server) { + app.context.beforeNuxtRender = fn => context.beforeRenderFns.push(fn) + app.context.beforeSerialize = fn => context.beforeSerializeFns.push(fn) + } + if (process.client) { + app.context.nuxtState = window.__NUXT__ + } + } + + // Dynamic keys + const [currentRouteData, fromRouteData] = await Promise.all([ + getRouteData(context.route), + getRouteData(context.from) + ]) + + if (context.route) { + app.context.route = currentRouteData + } + + if (context.from) { + app.context.from = fromRouteData + } + + if (context.error) { + app.context.error = context.error + } + + app.context.next = context.next + app.context._redirected = false + app.context._errored = false + app.context.isHMR = Boolean(context.isHMR) + app.context.params = app.context.route.params || {} + app.context.query = app.context.route.query || {} +} + +export function middlewareSeries (promises, appContext, renderState) { + if (!promises.length || appContext._redirected || appContext._errored || (renderState && renderState.aborted)) { + return Promise.resolve() + } + return promisify(promises[0], appContext) + .then(() => { + return middlewareSeries(promises.slice(1), appContext, renderState) + }) +} + +export function promisify (fn, context) { + let promise + if (fn.length === 2) { + console.warn('Callback-based asyncData, fetch or middleware calls are deprecated. ' + + 'Please switch to promises or async/await syntax') + + // fn(context, callback) + promise = new Promise((resolve) => { + fn(context, function (err, data) { + if (err) { + context.error(err) + } + data = data || {} + resolve(data) + }) + }) + } else { + promise = fn(context) + } + + if (promise && promise instanceof Promise && typeof promise.then === 'function') { + return promise + } + return Promise.resolve(promise) +} + +// Imported from vue-router +export function getLocation (base, mode) { + if (mode === 'hash') { + return window.location.hash.replace(/^#\//, '') + } + + base = decodeURI(base).slice(0, -1) // consideration is base is normalized with trailing slash + let path = decodeURI(window.location.pathname) + + if (base && path.startsWith(base)) { + path = path.slice(base.length) + } + + const fullPath = (path || '/') + window.location.search + window.location.hash + + return normalizeURL(fullPath) +} + +// Imported from path-to-regexp + +/** + * Compile a string to a template function for the path. + * + * @param {string} str + * @param {Object=} options + * @return {!function(Object=, Object=)} + */ +export function compile (str, options) { + return tokensToFunction(parse(str, options), options) +} + +export function getQueryDiff (toQuery, fromQuery) { + const diff = {} + const queries = { ...toQuery, ...fromQuery } + for (const k in queries) { + if (String(toQuery[k]) !== String(fromQuery[k])) { + diff[k] = true + } + } + return diff +} + +export function normalizeError (err) { + let message + if (!(err.message || typeof err === 'string')) { + try { + message = JSON.stringify(err, null, 2) + } catch (e) { + message = `[${err.constructor.name}]` + } + } else { + message = err.message || err + } + return { + ...err, + message, + statusCode: (err.statusCode || err.status || (err.response && err.response.status) || 500) + } +} + +/** + * The main path matching regexp utility. + * + * @type {RegExp} + */ +const PATH_REGEXP = new RegExp([ + // Match escaped characters that would otherwise appear in future matches. + // This allows the user to escape special characters that won't transform. + '(\\\\.)', + // Match Express-style parameters and un-named parameters with a prefix + // and optional suffixes. Matches appear as: + // + // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] + // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] + // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] + '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))' +].join('|'), 'g') + +/** + * Parse a string for the raw tokens. + * + * @param {string} str + * @param {Object=} options + * @return {!Array} + */ +function parse (str, options) { + const tokens = [] + let key = 0 + let index = 0 + let path = '' + const defaultDelimiter = (options && options.delimiter) || '/' + let res + + while ((res = PATH_REGEXP.exec(str)) != null) { + const m = res[0] + const escaped = res[1] + const offset = res.index + path += str.slice(index, offset) + index = offset + m.length + + // Ignore already escaped sequences. + if (escaped) { + path += escaped[1] + continue + } + + const next = str[index] + const prefix = res[2] + const name = res[3] + const capture = res[4] + const group = res[5] + const modifier = res[6] + const asterisk = res[7] + + // Push the current path onto the tokens. + if (path) { + tokens.push(path) + path = '' + } + + const partial = prefix != null && next != null && next !== prefix + const repeat = modifier === '+' || modifier === '*' + const optional = modifier === '?' || modifier === '*' + const delimiter = res[2] || defaultDelimiter + const pattern = capture || group + + tokens.push({ + name: name || key++, + prefix: prefix || '', + delimiter, + optional, + repeat, + partial, + asterisk: Boolean(asterisk), + pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?') + }) + } + + // Match any characters still remaining. + if (index < str.length) { + path += str.substr(index) + } + + // If the path exists, push it onto the end. + if (path) { + tokens.push(path) + } + + return tokens +} + +/** + * Prettier encoding of URI path segments. + * + * @param {string} + * @return {string} + */ +function encodeURIComponentPretty (str, slashAllowed) { + const re = slashAllowed ? /[?#]/g : /[/?#]/g + return encodeURI(str).replace(re, (c) => { + return '%' + c.charCodeAt(0).toString(16).toUpperCase() + }) +} + +/** + * Encode the asterisk parameter. Similar to `pretty`, but allows slashes. + * + * @param {string} + * @return {string} + */ +function encodeAsterisk (str) { + return encodeURIComponentPretty(str, true) +} + +/** + * Escape a regular expression string. + * + * @param {string} str + * @return {string} + */ +function escapeString (str) { + return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, '\\$1') +} + +/** + * Escape the capturing group by escaping special characters and meaning. + * + * @param {string} group + * @return {string} + */ +function escapeGroup (group) { + return group.replace(/([=!:$/()])/g, '\\$1') +} + +/** + * Expose a method for transforming tokens into the path function. + */ +function tokensToFunction (tokens, options) { + // Compile all the tokens into regexps. + const matches = new Array(tokens.length) + + // Compile all the patterns before compilation. + for (let i = 0; i < tokens.length; i++) { + if (typeof tokens[i] === 'object') { + matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$', flags(options)) + } + } + + return function (obj, opts) { + let path = '' + const data = obj || {} + const options = opts || {} + const encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent + + for (let i = 0; i < tokens.length; i++) { + const token = tokens[i] + + if (typeof token === 'string') { + path += token + + continue + } + + const value = data[token.name || 'pathMatch'] + let segment + + if (value == null) { + if (token.optional) { + // Prepend partial segment prefixes. + if (token.partial) { + path += token.prefix + } + + continue + } else { + throw new TypeError('Expected "' + token.name + '" to be defined') + } + } + + if (Array.isArray(value)) { + if (!token.repeat) { + throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`') + } + + if (value.length === 0) { + if (token.optional) { + continue + } else { + throw new TypeError('Expected "' + token.name + '" to not be empty') + } + } + + for (let j = 0; j < value.length; j++) { + segment = encode(value[j]) + + if (!matches[i].test(segment)) { + throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`') + } + + path += (j === 0 ? token.prefix : token.delimiter) + segment + } + + continue + } + + segment = token.asterisk ? encodeAsterisk(value) : encode(value) + + if (!matches[i].test(segment)) { + throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') + } + + path += token.prefix + segment + } + + return path + } +} + +/** + * Get the flags for a regexp from the options. + * + * @param {Object} options + * @return {string} + */ +function flags (options) { + return options && options.sensitive ? '' : 'i' +} + +export function addLifecycleHook(vm, hook, fn) { + if (!vm.$options[hook]) { + vm.$options[hook] = [] + } + if (!vm.$options[hook].includes(fn)) { + vm.$options[hook].push(fn) + } +} + +export const urlJoin = joinURL + +export const stripTrailingSlash = withoutTrailingSlash + +export const isSamePath = _isSamePath + +export function setScrollRestoration (newVal) { + try { + window.history.scrollRestoration = newVal; + } catch(e) {} +} diff --git a/examples/nuxt-example/.nuxt/vetur/tags.json b/examples/nuxt-example/.nuxt/vetur/tags.json new file mode 100644 index 00000000..c8b534b3 --- /dev/null +++ b/examples/nuxt-example/.nuxt/vetur/tags.json @@ -0,0 +1,11 @@ +{ + "NavBar": { + "description": "Auto imported from components/NavBar.vue" + }, + "NuxtLogo": { + "description": "Auto imported from components/NuxtLogo.vue" + }, + "Tutorial": { + "description": "Auto imported from components/Tutorial.vue" + } +} diff --git a/examples/nuxt-example/.nuxt/views/app.template.html b/examples/nuxt-example/.nuxt/views/app.template.html new file mode 100644 index 00000000..3427d3ea --- /dev/null +++ b/examples/nuxt-example/.nuxt/views/app.template.html @@ -0,0 +1,9 @@ + + + + {{ HEAD }} + + + {{ APP }} + + diff --git a/examples/nuxt-example/.nuxt/views/error.html b/examples/nuxt-example/.nuxt/views/error.html new file mode 100644 index 00000000..082a41fc --- /dev/null +++ b/examples/nuxt-example/.nuxt/views/error.html @@ -0,0 +1,23 @@ + + + +Server error + + + + + +
+
+ +
Server error
+
{{ message }}
+
+ +
+ + diff --git a/examples/nuxt-example/README.md b/examples/nuxt-example/README.md new file mode 100644 index 00000000..0d7b4641 --- /dev/null +++ b/examples/nuxt-example/README.md @@ -0,0 +1,69 @@ +# nuxt-app-example + +## Build Setup + +```bash +# install dependencies +$ npm install + +# serve with hot reload at localhost:3000 +$ npm run dev + +# build for production and launch server +$ npm run build +$ npm run start + +# generate static project +$ npm run generate +``` + +For detailed explanation on how things work, check out the [documentation](https://nuxtjs.org). + +## Special Directories + +You can create the following extra directories, some of which have special behaviors. Only `pages` is required; you can delete them if you don't want to use their functionality. + +### `assets` + +The assets directory contains your uncompiled assets such as Stylus or Sass files, images, or fonts. + +More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/assets). + +### `components` + +The components directory contains your Vue.js components. Components make up the different parts of your page and can be reused and imported into your pages, layouts and even other components. + +More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/components). + +### `layouts` + +Layouts are a great help when you want to change the look and feel of your Nuxt app, whether you want to include a sidebar or have distinct layouts for mobile and desktop. + +More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/layouts). + + +### `pages` + +This directory contains your application views and routes. Nuxt will read all the `*.vue` files inside this directory and setup Vue Router automatically. + +More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/get-started/routing). + +### `plugins` + +The plugins directory contains JavaScript plugins that you want to run before instantiating the root Vue.js Application. This is the place to add Vue plugins and to inject functions or constants. Every time you need to use `Vue.use()`, you should create a file in `plugins/` and add its path to plugins in `nuxt.config.js`. + +More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/plugins). + +### `static` + +This directory contains your static files. Each file inside this directory is mapped to `/`. + +Example: `/static/robots.txt` is mapped as `/robots.txt`. + +More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/static). + +### `store` + +This directory contains your Vuex store files. Creating a file in this directory automatically activates Vuex. + +More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/store). diff --git a/examples/nuxt-example/components/NavBar.vue b/examples/nuxt-example/components/NavBar.vue new file mode 100644 index 00000000..d29a68cb --- /dev/null +++ b/examples/nuxt-example/components/NavBar.vue @@ -0,0 +1,29 @@ +// components/NavBar.vue + + + + + diff --git a/examples/nuxt-example/components/NuxtLogo.vue b/examples/nuxt-example/components/NuxtLogo.vue new file mode 100644 index 00000000..970eba0e --- /dev/null +++ b/examples/nuxt-example/components/NuxtLogo.vue @@ -0,0 +1,11 @@ + + + diff --git a/examples/nuxt-example/components/Tutorial.vue b/examples/nuxt-example/components/Tutorial.vue new file mode 100644 index 00000000..6b96cf03 --- /dev/null +++ b/examples/nuxt-example/components/Tutorial.vue @@ -0,0 +1,52 @@ + + + + diff --git a/examples/nuxt-example/layouts/default.vue b/examples/nuxt-example/layouts/default.vue new file mode 100644 index 00000000..e6694f44 --- /dev/null +++ b/examples/nuxt-example/layouts/default.vue @@ -0,0 +1,32 @@ +// layouts/default.vue + + + + + diff --git a/examples/nuxt-example/nuxt.config.js b/examples/nuxt-example/nuxt.config.js new file mode 100644 index 00000000..8ce3d486 --- /dev/null +++ b/examples/nuxt-example/nuxt.config.js @@ -0,0 +1,50 @@ +export default { + // Global page headers: https://go.nuxtjs.dev/config-head + head: { + title: 'nuxt-app-example', + htmlAttrs: { + lang: 'en' + }, + meta: [ + { charset: 'utf-8' }, + { name: 'viewport', content: 'width=device-width, initial-scale=1' }, + { hid: 'description', name: 'description', content: '' }, + { name: 'format-detection', content: 'telephone=no' } + ], + link: [ + { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } + ] + }, + + // Global CSS: https://go.nuxtjs.dev/config-css + css: [ + ], + + // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins + plugins: [ + ], + + // Auto import components: https://go.nuxtjs.dev/config-components + components: true, + + // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules + buildModules: [ + ], + + // Modules: https://go.nuxtjs.dev/config-modules + modules: [ + ], + + // Build Configuration: https://go.nuxtjs.dev/config-build + build: { + transpile: ['@azure/app-configuration-provider'], // Add the Azure package to transpile + loaders: { + js: { + transpileOnly: true, // Skip type-checking for JS files + } + }, + esbuild: { + target: 'esnext', // Make sure it's targeting modern JavaScript + } + } +} diff --git a/examples/nuxt-example/package.json b/examples/nuxt-example/package.json new file mode 100644 index 00000000..62902d8e --- /dev/null +++ b/examples/nuxt-example/package.json @@ -0,0 +1,26 @@ +{ + "name": "nuxt-app-example", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "nuxt", + "build": "nuxt build", + "start": "nuxt start", + "generate": "nuxt generate" + }, + "dependencies": { + "@azure/app-configuration-provider": "^1.1.3", + "core-js": "^3.25.3", + "nuxt": "^2.15.8", + "vue": "^2.7.10", + "vue-loader": "^17.4.2", + "vue-server-renderer": "^2.7.10", + "vue-template-compiler": "^2.7.10" + }, + "devDependencies": { + "@babel/core": "^7.26.0", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/preset-env": "^7.26.0", + "babel-loader": "^9.2.1" + } +} diff --git a/examples/nuxt-example/pages/about.vue b/examples/nuxt-example/pages/about.vue new file mode 100644 index 00000000..20ea6a43 --- /dev/null +++ b/examples/nuxt-example/pages/about.vue @@ -0,0 +1,20 @@ +// pages/about.vue + + + + + diff --git a/examples/nuxt-example/pages/index.vue b/examples/nuxt-example/pages/index.vue new file mode 100644 index 00000000..e0bbb5ae --- /dev/null +++ b/examples/nuxt-example/pages/index.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/examples/nuxt-example/static/favicon.ico b/examples/nuxt-example/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d751f60c6d606d10dc8fcc6200b4dd747dd1e1ce GIT binary patch literal 8636 zcmc&)^-~+n(+^&tXp6gBgMJ~nTX3g%ixw%+0L3jpixdm)!KGMnZAyXSZpA6?8l1q( z^H;okb8~yMKiq!S=4NLB0JP`zAE5yl0VPZT0QoZ?rK6=nfJcq@%o2cA74`m;{V_AhDIUiN=_x{uRUY_%}lF~~WR$;EkAC!Lwx?ZMK;eOry75s9MeHn{G=mFvRMXh@|w*v6TX=LTCnjS(7@=hZsdL z#q2QAD}eyfSXd1KKxPZ|54qz2K4$bSPpdO#9u$2I=4Hv)1UmDy0CqU|FhSJ96;A2Ap9BG6a>fMfXIlCAhEwcB_m69bIi6JSk(xk61e zT_eedZgl`4+xLpc3Q@0ldyvOsVq&v(azy^{8z1$FmPl3u00_@_eNT9IR{taloAJ_n zTsapKL|@!H42hQl00cG**OsJNV`$(HYL7~!KE8;ISb#YiAmQ}B@OKUgtBhO1xtWOy z@2^h}W5Mq9SLguhxJ#3<*N55m=XX*BsSFpC1~jOD$hRPoSw-#h*} zAn*+Un7+O;27Q#4NPm6ePskZeG)EWS#mp_S{XXa*;hg7IV&LrVe*0Yw0DjdR{AcCSiofwzDsG^26YmhNpX7rDkUb*4 z6WKus4HOb`BVZs^-tlE9)gcvNdV3o*ELnWQiNPO;!Avw~i%a$0TWRSzqo#jfJ3Ivk z!(iQmZg$mk|3IJG1k-vS(SH4M4UVgHQ;PPoc$th)@n*gIx);J|i3S)Cu8f=vQu&0T zCHXQ0W;Kcbt|bj8pAvZFqkU~TSGy-j%t+f=kC9Mrt-h~P&D=+H$|X?7aE7-jYq zw#SwoK(X2gCvr|g0Xh-qI3hRKT6%B}>#_&671rA?#+hIQ2H!L8mlZ2kR3Q$xw|TMU z=Vp7X^ZGtWi^efZ;nj1& zzwAIvsZg|)$F^q6VpLEzV9U5JbyMM?{aio*@R>H#5UDq=xGM9-mhW!tghMPlSf9y< zh)9d;X3^(b^T>{J!RrAVQ1RQ4Xwgjh?5H!H7z4g(qz5AjQ0E;LcM0%c-o2&LL@xU$ zWXqkug7vB93dCyHWCp!V$vk2UFseoZ;rfSl)oYe+g_KM%k*I8jQ{4Q&!bNli#0kLV54j znYXNNa#kLquV*JtQOT}PbVzkTw?W9t?l(Uak+57zZupR)rGU`eB{ELz*)2a~x)en7 zL&Br)qOvjo(6XqF^VqbV;Xhy;#5R@`poj#U=TH^(QJqG^LHVSmwzp$F_qDUKQAG3p2>>d5DG?RN988JQDC#`<6_d8hECq{a-~ zXnqrA2ua3z6n&BGxc$Qvw$++Xy-h;<-V&X3Ri|Jv*eVDudB5^S(|Zo2;o8ZV);9zF zr6|%*#InQ|x_5hlnKIgyay#x8cNKaN^FH3<7ju3&j|pv4UsHI1h;`NCEp9=z6Q%E- z70EKr7h~NTGa1wW+B02$Z(BClz`~SgBJ1NFmCE#SEV{fKC(qdz!rtH6L5*e4&o*ff z!g4>f4YCqiRBKGW&+SzrOTgnLp%s4g_d|0TTGewN4S_lS8L%@bwrlrTihA!34T@@n zN(fAF&YShG{*X&?$l_M-95)kMEMg)!s1?E7@am51_b%7y$#9`5w2Tas;Gj0ji0I5ZR+finZ`9q6=X@!u0 zm{BEIwipy_#1qV`M@)ne*VZ(fzK4Ejn0~$UWk*Yq+WEe zW!OI+lYWz}a}BO~%fM>F0;-N_Jrr4vN*!8Ai*CrjbE`?9`@Jegoc9*x7IO&6vD%=2 z@*AL*X7Ryd1)lbyHT`R7MUYCGr%fGAHuQ!WiWuo@G|8@;Suu)znJON-%V3Ci4R*ae ziVQtBYmFEkaxZOt70O*J=uEWE#mW~GdpH}dW6~AnhwCY%Gz-EEO9`G{ibQ?LIx=$< zUa9l67(#Rh4&NpTC)^y*`LbqiZPa{` z>x)$z3hl?xEx`^%|0Dv?ZC>q#g7%h?bT$>%`Tyct$t_rju{oZtM=>cAY%Ii)f9~d8 zI0=C(-)EU;V{OCJ3l767NEdZ>8Os~yN(-4N45?}=NAid$jEa8oSQH^jVccRMZlE($ zK9xNBXvhs$Fav`@-N3f8prS&fJhJf5&%@uU_I#;Rru6-4<75WJ?qoF$mBqtz$?I^U znAM{i6sXt#I@`RID($Bes7OY~mMlAZ=zpK$OtnaYMaOQrhHZQ4Re!Xa3)=*n(R*2fAsH1U72uIxU7&ub+UVx%Z10%%vIanr zvf7k`eLwrIc2hQBOZ&XJGRq8Sqa?`cvnYrR{6~b|k?yq@eku=8o4m5YCH(bB&-$Im zf3R-hZ8x?rE*8PcL--#R4*m!jmk{|Q-bE}6Ar}dOIH(>TU{YVs3j-Q1xB9PVh0wz` zr;@cUFCYUj!&o+V3JMdxlDU99>MV=!SUS%Cr6Od?`B59U6eTN@EWfJkw7bE8N%Zx^ z>n3b}MVT5)93_R>erQ>6DZN73-igTrv}=7OK}_uV>w4_1Wv39qS3x2uF>MGTiV~xh2f@e>4T7*z{lKcIKg_+I<~+ zC5WYn3t@*)R`2zQ*kuoRGas$M4y|mR#x7$ei&!Q?!Ej%gRQ=;&m`coYx*&!uFGW2? z@Ng|fZb7w{zM-5Lei25WL39cU<2gPxqbo-G*l zwZQVp20Rrjbg$2)@G+FxOX8^ zhZxn_#Xy9u;|I!1T#e1dxdEe~BS`s5n4wT3TEM08K6AS3!@19YAzI+pylQYk`#KsO zr` zt%ZCrpny+8z1aY%sOn4P~ff9-|1y_m-AJP z{qm>(S$V}^r7v=fDTunMrlZ~Ppqg?Dw+ov)Lztz}2P_lFSaHt0J(qKk@0PEQT`N*@Zsa&GWTCGyo|06m4cVHJ)(Jb&tT zMs=IIj7059S7ukE=p9@7%WR_Ww#KF_P8*D+xO&OJ0;#`ry>gAB{l(urGY)FNiOO~I zz2z4NDXpCw><2a_4+~qSfhL#2SE<5W!*RrU_-CRy7RVP!g9?qH5 z-IuNh;HSfTUS*3UoU?BTA5Mf{Q{Hb!1X~r#quroGwjC{uz%4}5+nPif9__H?Vz%@N zno-O1!&eL@W%IG?DE#00%PnO)YiocjTf_vfG4JBjs%4OzmViGOh|V;J;S|Tn&p9I& zzqJ}gKXH3HHe8e?v#q-X=^m~&uRm@&mvPQLY6RzVVN427)sd?gW1W;VGGL5`sJT`0 zTBV`Lq4=0$tFQY|q7H2+?2c-ZPx~fNy5y98vZ96&;e+~qrFr7UH2m5U9;R4Q7Yf1bC<4(-?VsHNs|)R5}N4+|T36R-%1tW!Y9?DSS!I+JE6_En<+?eJb}66$RTB zrC?r?|9#H0GcMf`-0fURFPpQH)-!Wa4@xMJeD6ci<)~&f9d3hq!z;qLSWw55DRGA0 zmFR@O`z;pBA%x(83!@fFv^j_6(Ri(#rKj38^#;^U9mTBc6aKo@E#V0hd&{*X!|HnHwIDa)v z$0w=>R6zu)bz4fi(u8Q#yLVpk`E(eWQd)F>C>!*d@?=T5y5}Y`aP*9ih!qYu*^^G< zY2D>IDMga$RL?xtzU!NFhGoaL~gBPFXW1Kqwn5a<;&n(69_U%Aq;B-c z%zP3bc_*wFhDEgCuv-q@%82>!kE4YBwAA&HnP$05qmj*fcZPMN%6Ei~Diu%nJMuWQ zOT`xWSe_BnPx)CxJ?i}WQjUQ{<35LPJuI5;=JWj_Dw5IrXXcK(YAM94O{G=?|Z(@rSEy3aC7yyju%OpPGJ8dD#2WRcTspOoR5LAv!vcq6NfT z3UT|a6R=>857+L+HPihK#*kqoysZi^|Z4BF0+{ z)h{0yM3kdC6V69(;2_a|VIs(xUeK}@^p&TTO*Dk;=3uy`QF^Ix%(PF9(Xq?7jM!pZj-0oO$AknF&Htv)-ll%rQd?kk% z*8bj0#YeaMqxoq98YY*j!cxC6ZkI9i*7(w;i=AtdBzVVGgRHK3JoB?715#V-9xjX+ zLHEy!Em-w$AJ0Ve8ftVCjWJo3Q6B<{&g&%xiivP5L zQ`OgY&@yBKT@J!`T=t%M{Z;_dI=B?ohX>*KJh5=(VBVs51E0gYgUdum5Si9v&>A*_ zN6~x?X&9`8r26(Rlf5D&&TuT5B*Mo&O15M9AId$X!-*C?GOz8yZMMbn#ozECN@k^a zb|K4J2U6Tkf#iuKmu#)CW)3zsI!eEZ$;e!kVW3*BiYP@(YM*N|Jmdl1 zLpY>)(>w39m#gX1Zc=EZ%LYqxsni)75N}Da%;U*CTh(k`uC+CU&3?{Q?`1$K=3m`0 z$8_`jx`Rs+u@L%*_J)B_G!&YxTF0zGQxG2G-xY*A1>rNMo*51A(y5rUM<0KrT{KVnZ5NQZ zcjEwI%pDQ}Hl58k>w``hwZDxu-+Zjoe6zHhGVI0I*Lbxh#GYm$ruC}4&1m#Ej>xZk zE{Bo9GvBmTOF-xVq%8k`Y0Zfs}@?U027wO-rY8Pipw}`qnu9 zu7{3;Ik6h9kixPdyQnv?CF_r7-)E?jHtMD|Kkh?$TIyzxZ{Vf%L~ZWM;^@IK_KU8F z4ZHG6Xs3R6Rm+FApXPX7J7CLHXXk5dfnKsU zlX8+o{t&z7>vo;%O2?|rupLcg$}jzai%m(UVpe`taR*yiB(TFE9{pJK*QK>U^En_3{)SR0_#G~~)f!^49uaS14fxHvx;1UZH19P_dDJrv)sr#P&@uP_LW|lx{H;%12+HA#fdr z{p6RS!>MMmaeI0Neq`E)kU_c12bx@Pujy?Lth7jIA?@kNPu4wMiKGljVf(vQvkGZ{<(>TuxIcVasOG%e)3BAFz zdga+lKJFKtkx}0USvqpVK=!%Wj(I3-vq0=Nl%RstNICLb%sw0KR(gyE%z#vs4u8sm{#a=mS5rx2`>O9bzM?I^ zRwIubu2sGl+6MFfa8Mt3p;wZfF!(KZfX>l{{|a66y!>}#Op9v# z4zi=WZHgoD7?WQj$drFS!8%qy6&%V;aE@`TTiOd6o<9K_fo+R?{|3j{N`A(+(gM?+ z3?be<(n$&v+P$2Y;FKEDn8n&r!Xk^exAWqsLQs6SO~Q3^J{R?$M1yh&^&=pJUk0%? zYp#+!Lr_;qr)EKL)42Ivwo$y^1M~Wnd~|8^-Uf5}{b9O2Mlc6{U0#`BpA_jySjBp5 z<7yMOw{{mJEF~}LrKVT+SO_{akq16{%sc_{Ee5sj84^-9zA0-vKR}aXKn7Gd8r38g zDL=OFUIX#{c%Gzw4kY~3%JXaY_&(S$eA@e-Ks5K27k)+Rtpt|YHs6(+(04|XST$`_r^a>K z%lS}dYH$V7UyJSwsxY;edC9%aLio59J z-F7I>nL`v(E@gcYt|9izFVwvO0op=}4S#QGAR9DWH2$Siatd2q{N8EKpYG*YKO+C$ zAn|w@SQzs_Owd$J2s8Qo3)8y#RBde$AX^o#P^mx*V;0yZjDeA@orEp4Kse zn52cpfZF24JQc}hb{}E~wm&$AAQa5ymR)D7v-cf3>JJs`avbMRI*ChM3nbQ7&5%0$ zZ$a6GL$uxw#mo2&WigECj1>i|zG5T5wf^~o9RR&%!1Kbgvj<{GQ+Vrl-RO25|xyV^qNrAwLO#XzhD z57}E>9CJOpYx3B<%bvu9ET)th0KH4#nGoKZ3OYmK$+9PFC zlp#FHrQnY>rSsM@w6H#@t`Y{-jcA!_#$E<;LqQR|!Ew*CH{dZ(sh?3O_ct^l<}T|g zPo)9(3z5MrzGQ{xAA({0eN49c9+C9z~Nq*l5@d)i2G!LS0|V^WXTZ5p8ycp|bCxDa(&?!r(BBNL}Bo|Ugy zQB{a1f4w^lB!J8+b+moy2-KTYnEcg%-Dzzs?sGRUl!jPBx7$=mx3)%zXRNRvo3XG> zea9v^8zIWO+lxbd7!6x{`!Ux#SqwIxq@b|LHL`8SE{Ec;P|r#0>)`*Z^r|a7v}#Uz z$m44vecdOn$sh~T<-1AkM}h-X%%kev#oS+x9U&#FX@iiXCiA4iCKk#0J+=hRA!=0R z)%CWBrPl$1zc1(0-k7CJOpuns`;3co8*v$S{plvTQ+A~H#b)W0{2lk>WrN9A-`l3` z{yAgpclj)XRwarICj+{J3fxKU;LjJ#@;dllNpG?od0MXC&r-fgwG9$++ZQ4{hjbB- zk$Sg@a3p#>dVW?*LH^ne|jZcU4YvLjLi<$`gtV|_&2+lu@3X=&s7!*xjKxsHCHvf%J4XW1Ao(giQajn z;xw)KDPI_8MLssG5*A<5=d;|&`JyM*UmVwc*_<-wdz~=Y=3j2^>N$TQUPp!*JJZFJ z!PO;Z75iFxQXhj=2Pk^F;+#Y8pNt_8vF2iW;C;bA3#(c*cFz4|c2?*iI8=g~zP+Kj zn&Z-Ka7M6*MfX7$KY1CpCVWn=B_!m=+l!w>JXM$8E?I>jnst3gDAf#$l2}^PHkDy- z1_m19a3;m$&f1_Q{iVhS?V^8sdW^p2rvyuAyAG2Toj5~sCPq&7)wA^LFuu{157t4W z#62+ml#_zAZYuijUuvHX@4cH@N*;94j=%dE>E>w|Z}mcYeNVty!ngNbvhkouT8!;W zwzTN_e!E+k;^sfon$9d;!T1N(lx1=Z8y&?$*h&snl+(4c!!WSv>h$?w4V$lk z5(a%$*=mQpRG5S5pT%bN2@N7kQ5Dc2E3S6p_c~6Y{)3DI-vhmtC*J;xqoS}QyXy&& z(3wur!}7}10Fj)++^X>Hh@#COl@hJD%J8W<*fz>res@^P5lQm@FmDi|cIqa=Rg_F? TAMreE0RVuNv=po5-$DNmO`MKU literal 0 HcmV?d00001 diff --git a/examples/nuxt-example/store/README.md b/examples/nuxt-example/store/README.md new file mode 100644 index 00000000..1972d277 --- /dev/null +++ b/examples/nuxt-example/store/README.md @@ -0,0 +1,10 @@ +# STORE + +**This directory is not required, you can delete it if you don't want to use it.** + +This directory contains your Vuex Store files. +Vuex Store option is implemented in the Nuxt.js framework. + +Creating a file in this directory automatically activates the option in the framework. + +More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store).