diff --git a/change/@itwin-node-cli-authorization-cd9b1e0d-dbd2-4a0a-8305-caef61275076.json b/change/@itwin-node-cli-authorization-cd9b1e0d-dbd2-4a0a-8305-caef61275076.json new file mode 100644 index 00000000..897dbf02 --- /dev/null +++ b/change/@itwin-node-cli-authorization-cd9b1e0d-dbd2-4a0a-8305-caef61275076.json @@ -0,0 +1,7 @@ +{ + "type": "major", + "comment": "Move from cjs to esm and use Conf", + "packageName": "@itwin/node-cli-authorization", + "email": "50554904+hl662@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/node-cli/package.json b/packages/node-cli/package.json index 8d1ea597..d08aeeb8 100644 --- a/packages/node-cli/package.json +++ b/packages/node-cli/package.json @@ -1,22 +1,26 @@ { "name": "@itwin/node-cli-authorization", "version": "1.0.1", - "main": "lib/cjs/index.js", - "types": "lib/cjs/index.d.ts", + "type": "module", "description": "Node.js command-line authorization client for iTwin platform", + "engines": { + "node": ">=18" + }, "scripts": { - "build": "npm run -s build:cjs", - "build:cjs": "tsc 1>&2 --outDir lib/cjs && npm run copy:assets", - "copy:assets": "cpx src/static/* lib/cjs/static", + "build": "npm run -s build:esm", + "build:esm": "tsc 1>&2 --outDir lib/esm && npm run copy:assets", + "copy:assets": "cpx src/static/* lib/esm/static", "clean": "rimraf lib", "docs": "RUSHSTACK_FILE_ERROR_BASE_FOLDER='../..' betools docs --includes=../../generated-docs/extract --json=../../generated-docs/auth-clients/node-cli-authorization/file.json --tsIndexFile=./index.ts --onlyJson", "lint": "eslint -f visualstudio \"./src/**/*.ts\" 1>&2", "lint:fix": "npm run lint -- --fix", - "test": "mocha \"./lib/cjs/test/**/*.test.js\"", + "test": "mocha \"./lib/esm/test/**/*.test.js\"", "cover": "nyc npm test", "pack": "npm pack", "rebuild": "npm run clean && npm run build" }, + "exports": "./lib/esm/index.js", + "typings": "./lib/esm/index.d.ts", "author": { "name": "Bentley Systems, Inc.", "url": "http://www.bentley.com" @@ -28,20 +32,19 @@ "directory": "packages/node-cli" }, "dependencies": { - "@itwin/core-common": "^3.3.0 || ^4.0.0", + "@itwin/core-common": "^4.0.0", "@openid/appauth": "^1.3.1", - "node-persist": "^3.1.3", + "conf": "^11.0.2", "open": "^8.3.0", "username": "^5.1.0" }, "devDependencies": { - "@itwin/build-tools": "^4.0.0-dev.93", - "@itwin/core-bentley": "^3.7.0", + "@itwin/build-tools": "^4.0.0", + "@itwin/core-bentley": "^4.0.0", "@itwin/eslint-plugin": "^3.7.0", "@types/chai-as-promised": "^7.1.1", "@types/chai": "^4.2.22", "@types/mocha": "^8.2.3", - "@types/node-persist": "^3.1.3", "@types/node": "^18.11.5", "@types/sinon": "^10.0.16", "chai-as-promised": "^7.1.1", @@ -56,7 +59,7 @@ "typescript": "~5.0.2" }, "peerDependencies": { - "@itwin/core-bentley": "^3.3.0 || ^4.0.0" + "@itwin/core-bentley": "^4.0.0" }, "eslintConfig": { "plugins": [ diff --git a/packages/node-cli/src/Client.ts b/packages/node-cli/src/Client.ts index a6f8d8f7..c73b0327 100644 --- a/packages/node-cli/src/Client.ts +++ b/packages/node-cli/src/Client.ts @@ -11,15 +11,15 @@ import { readFileSync } from "fs"; import * as path from "path"; import * as Http from "http"; -import * as open from "open"; +import open from "open"; import { assert, BeEvent, BentleyError, Logger } from "@itwin/core-bentley"; import { AuthorizationError, AuthorizationNotifier, AuthorizationRequest, AuthorizationRequestHandler, AuthorizationResponse, AuthorizationServiceConfiguration, BaseTokenRequestHandler, BasicQueryStringUtils, GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_REFRESH_TOKEN, TokenRequest, } from "@openid/appauth"; -import { NodeCrypto, NodeRequestor } from "@openid/appauth/built/node_support"; -import { TokenStore } from "./TokenStore"; +import { NodeCrypto, NodeRequestor } from "@openid/appauth/built/node_support/index.js"; +import { TokenStore } from "./TokenStore.js"; import type { AccessToken } from "@itwin/core-bentley"; import type { AuthorizationClient } from "@itwin/core-common"; @@ -152,8 +152,6 @@ export class NodeCliAuthorizationClient implements AuthorizationClient { // Would ideally set up in constructor, but async... if (!this._configuration) this._configuration = await AuthorizationServiceConfiguration.fetchFromIssuer(this._bakedConfig.issuerUrl, new NodeRequestor()); - - await this._tokenStore.initialize(); } private async loadAndRefreshAccessToken() { diff --git a/packages/node-cli/src/TokenStore.ts b/packages/node-cli/src/TokenStore.ts index 867d2aaa..2dc3fc7c 100644 --- a/packages/node-cli/src/TokenStore.ts +++ b/packages/node-cli/src/TokenStore.ts @@ -3,14 +3,17 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as OperatingSystemUserName from "username"; import type { TokenResponseJson } from "@openid/appauth"; +import OperatingSystemUserName from "username"; import { TokenResponse } from "@openid/appauth"; import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from "node:crypto"; -import * as path from "node:path"; -import * as NodePersist from "node-persist"; +import Conf from "conf"; type CacheEntry = TokenResponseJson & {scopesForCacheValidation?: string}; +interface ConfEntry { + encryptedCache: string; + iv: string; +} /** * Utility to store OIDC AppAuth in secure storage * @internal @@ -18,7 +21,7 @@ type CacheEntry = TokenResponseJson & {scopesForCacheValidation?: string}; export class TokenStore { private readonly _appStorageKey: string; private readonly _scopes: string; - private readonly _store: NodePersist.LocalStorage; + private readonly _store: Conf; public constructor(namedArgs: {clientId: string, issuerUrl: string, scopes: string}, dir?: string) { // A stored credential is only valid for a combination of the clientId, the issuing authority and the requested scopes. // We make the storage key a combination of clientId and issuing authority so that keys can stay cached when switching @@ -29,14 +32,25 @@ export class TokenStore { .replace(/[.]/g, "%2E") // Replace all '.' with URL Percent-encoding representation .replace(/[\/]/g, "%2F"); // Replace all '/' with URL Percent-encoding representation; this._scopes = namedArgs.scopes; - this._store = NodePersist.create({ - dir: dir ?? path.join(process.cwd(), ".configStore"), // specifies storage file path. - }); - } - public async initialize(): Promise { - await this._store.init(); + let confConfig: object = { + configName: configFileName, // specifies storage file name. + encryptionKey: "iTwin", // obfuscates the storage file's content, in case a user finds the file and wants to modify it. + }; + if (dir) { + confConfig = { + ...confConfig, + cwd: dir, // specifies the directory that contains the storage file. + }; + } else { + confConfig = { + ...confConfig, + projectName: configFileName, // specifies the directory that contains the storage file. + }; + } + this._store = new Conf(confConfig); } + private _userName?: string; private async getUserName(): Promise { if (!this._userName) @@ -60,7 +74,7 @@ export class TokenStore { * Uses node's native `crypto` module to encrypt the given cache entry. * @returns an object containing a hexadecimal encoded token, returned as a string, as well as the initialization vector. */ - private encryptCache(cacheEntry: CacheEntry): {encryptedCache: string, iv: string} { + private encryptCache(cacheEntry: CacheEntry): ConfEntry { const iv = randomBytes(16); const cipher = createCipheriv("aes-256-cbc", this.generateCipherKey(), iv); @@ -86,18 +100,17 @@ export class TokenStore { return undefined; const key = await this.getKey(); - const storeKeys = await this._store.keys(); - if (!storeKeys.includes(key)) { + if (!this._store.has(key)) { return undefined; } - const storedObj = await this._store.getItem(key); + const storedObj = this._store.get(key) as ConfEntry; const encryptedCache = storedObj.encryptedCache; const iv = storedObj.iv; const cacheEntry = this.decryptCache(encryptedCache, Buffer.from(iv, "hex")); // Only reuse token if matching scopes. Don't include cache data for TokenResponse object. const tokenResponseObj = JSON.parse(cacheEntry) as CacheEntry; if (tokenResponseObj?.scopesForCacheValidation !== this._scopes) { - await this._store.removeItem(key); + this._store.delete(key); return undefined; } delete tokenResponseObj.scopesForCacheValidation; @@ -124,6 +137,6 @@ export class TokenStore { }; const objToStore = this.encryptCache(cacheEntry); const key = await this.getKey(); - await this._store.setItem(key, objToStore); + this._store.set(key, objToStore); } } diff --git a/packages/node-cli/src/index.ts b/packages/node-cli/src/index.ts index 979110fa..9d9ac1f6 100644 --- a/packages/node-cli/src/index.ts +++ b/packages/node-cli/src/index.ts @@ -2,7 +2,7 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -export * from "./Client"; +export * from "./Client.js"; /** @docs-package-description * Provides auth functionality for node command-line applications. diff --git a/packages/node-cli/src/test/Client.test.ts b/packages/node-cli/src/test/Client.test.ts index d4cdc587..0402cc64 100644 --- a/packages/node-cli/src/test/Client.test.ts +++ b/packages/node-cli/src/test/Client.test.ts @@ -3,21 +3,21 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; -import * as chaiAsPromised from "chai-as-promised"; +import { expect, use } from "chai"; +import chaiAsPromised = require("chai-as-promised"); -import { BakedAuthorizationConfiguration } from "../Client"; -import type { NodeCliAuthorizationConfiguration } from "../Client"; +import { BakedAuthorizationConfiguration } from "../Client.js"; +import type { NodeCliAuthorizationConfiguration } from "../Client.js"; -chai.use(chaiAsPromised); +use(chaiAsPromised); describe("NodeCliAuthorizationConfiguration defaults", () => { it("should throw if clientId is an empty string", () => { - chai.expect(() => new BakedAuthorizationConfiguration({ clientId: "", scope: "testScope" })).to.throw(); + expect(() => new BakedAuthorizationConfiguration({ clientId: "", scope: "testScope" })).to.throw(); }); it("should throw if scope is an empty string", () => { - chai.expect(() => new BakedAuthorizationConfiguration({ clientId: "testClientId", scope: "" })).to.throw(); + expect(() => new BakedAuthorizationConfiguration({ clientId: "testClientId", scope: "" })).to.throw(); }); }); @@ -31,31 +31,31 @@ describe("NodeCliAuthorizationConfiguration Authority URL Logic", () => { it("should use config authority without prefix", async () => { process.env.IMJS_URL_PREFIX = ""; const bakedConfig = new BakedAuthorizationConfiguration({ ...config, issuerUrl: testAuthority }); - chai.expect(bakedConfig.issuerUrl).equals(testAuthority); + expect(bakedConfig.issuerUrl).equals(testAuthority); }); it("should use config authority and ignore prefix", async () => { process.env.IMJS_URL_PREFIX = "prefix-"; const bakedConfig = new BakedAuthorizationConfiguration({ ...config, issuerUrl: testAuthority }); - chai.expect(bakedConfig.issuerUrl).equals("https://test.authority.com"); + expect(bakedConfig.issuerUrl).equals("https://test.authority.com"); }); it("should use default authority without prefix ", async () => { process.env.IMJS_URL_PREFIX = ""; const bakedConfig = new BakedAuthorizationConfiguration(config); - chai.expect(bakedConfig.issuerUrl).equals("https://ims.bentley.com"); + expect(bakedConfig.issuerUrl).equals("https://ims.bentley.com"); }); it("should use default authority with prefix ", async () => { process.env.IMJS_URL_PREFIX = "prefix-"; const bakedConfig = new BakedAuthorizationConfiguration(config); - chai.expect(bakedConfig.issuerUrl).equals("https://prefix-ims.bentley.com"); + expect(bakedConfig.issuerUrl).equals("https://prefix-ims.bentley.com"); }); it("should reroute dev prefix to qa if on default ", async () => { process.env.IMJS_URL_PREFIX = "dev-"; const bakedConfig = new BakedAuthorizationConfiguration(config); - chai.expect(bakedConfig.issuerUrl).equals("https://qa-ims.bentley.com"); + expect(bakedConfig.issuerUrl).equals("https://qa-ims.bentley.com"); }); }); @@ -67,7 +67,7 @@ describe("NodeCliAuthorizationConfiguration Config Scope Logic", () => { it("Should add offline_access scope", async () => { const bakedConfig = new BakedAuthorizationConfiguration(config); - chai.expect(bakedConfig.scopes).equals(`${config.scope} offline_access`); + expect(bakedConfig.scopes).equals(`${config.scope} offline_access`); }); it("Should not add offline_access scope", async () => { @@ -75,7 +75,7 @@ describe("NodeCliAuthorizationConfiguration Config Scope Logic", () => { clientId: "testClientId", scope: "testScope offline_access", }); - chai.expect(bakedConfig.scopes).equals("testScope offline_access"); + expect(bakedConfig.scopes).equals("testScope offline_access"); }); }); diff --git a/packages/node-cli/src/test/TokenStore.test.ts b/packages/node-cli/src/test/TokenStore.test.ts index 40b8de43..5d8c4841 100644 --- a/packages/node-cli/src/test/TokenStore.test.ts +++ b/packages/node-cli/src/test/TokenStore.test.ts @@ -1,10 +1,10 @@ import { TokenResponse } from "@openid/appauth"; -import * as chai from "chai"; -import * as chaiAsPromised from "chai-as-promised"; -import { TokenStore } from "../TokenStore"; +import { assert, expect, use } from "chai"; +import chaiAsPromised = require("chai-as-promised"); +import { TokenStore } from "../TokenStore.js"; import { rmSync } from "fs"; -import * as sinon from "sinon"; -chai.use(chaiAsPromised); +import { spy } from "sinon"; +use(chaiAsPromised); describe("TokenStore", () => { let tokenStore: TokenStore; @@ -20,7 +20,6 @@ describe("TokenStore", () => { issuerUrl: "https://testUrl.com", scopes: "testScope1 testScope2", }, `${process.cwd()}/testConfig`); - await tokenStore.initialize(); }); afterEach(() => { @@ -31,9 +30,9 @@ describe("TokenStore", () => { if (process.platform === "linux") return; - const saveSpy = sinon.spy(tokenStore as any, "encryptCache"); + const saveSpy = spy(tokenStore as any, "encryptCache"); await tokenStore.save(testTokenResponse); - chai.assert.isTrue(saveSpy.calledOnce); + assert.isTrue(saveSpy.calledOnce); }); it("should decrypt cache on load", async () => { @@ -43,7 +42,7 @@ describe("TokenStore", () => { await tokenStore.save(testTokenResponse); const retrievedToken = await tokenStore.load(); - chai.expect(retrievedToken!.refreshToken).equals(testTokenResponse.refreshToken); + expect(retrievedToken!.refreshToken).equals(testTokenResponse.refreshToken); }); it("load() should return undefined when scopes are mismatched", async () => { @@ -57,9 +56,8 @@ describe("TokenStore", () => { issuerUrl: "https://testUrl.com", scopes: "testScope1 testScope2 testScope3", }, `${process.cwd()}/testConfig`); - await tokenStore2.initialize(); const retrievedToken = await tokenStore2.load(); - chai.expect(retrievedToken).to.be.undefined; + expect(retrievedToken).to.be.undefined; }); }); diff --git a/packages/node-cli/tsconfig.json b/packages/node-cli/tsconfig.json index fb91327c..4b415343 100644 --- a/packages/node-cli/tsconfig.json +++ b/packages/node-cli/tsconfig.json @@ -1,8 +1,9 @@ { "extends": "./node_modules/@itwin/build-tools/tsconfig-base.json", "compilerOptions": { - "target": "es2021", - "module": "commonjs", + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", "outDir": "./lib" }, "include": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1868b37..294c3192 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,23 +120,22 @@ importers: packages/node-cli: specifiers: - '@itwin/build-tools': ^4.0.0-dev.93 - '@itwin/core-bentley': ^3.7.0 - '@itwin/core-common': ^3.3.0 || ^4.0.0 + '@itwin/build-tools': ^4.0.0 + '@itwin/core-bentley': ^4.0.0 + '@itwin/core-common': ^4.0.0 '@itwin/eslint-plugin': ^3.7.0 '@openid/appauth': ^1.3.1 '@types/chai': ^4.2.22 '@types/chai-as-promised': ^7.1.1 '@types/mocha': ^8.2.3 '@types/node': ^18.11.5 - '@types/node-persist': ^3.1.3 '@types/sinon': ^10.0.16 chai: ^4.2.22 chai-as-promised: ^7.1.1 + conf: ^11.0.2 cpx2: ^5.0.0 eslint: ^7.32.0 mocha: ^8.2.3 - node-persist: ^3.1.3 nyc: ^15.1.0 open: ^8.3.0 rimraf: ^3.0.2 @@ -145,20 +144,19 @@ importers: typescript: ~5.0.2 username: ^5.1.0 dependencies: - '@itwin/core-common': 4.0.6_@itwin+core-bentley@3.7.12 + '@itwin/core-common': 4.0.6_@itwin+core-bentley@4.1.2 '@openid/appauth': 1.3.1 - node-persist: 3.1.3 + conf: 11.0.2 open: 8.4.2 username: 5.1.0 devDependencies: '@itwin/build-tools': 4.0.6_@types+node@18.17.1 - '@itwin/core-bentley': 3.7.12 + '@itwin/core-bentley': 4.1.2 '@itwin/eslint-plugin': 3.7.8_cgdknpc562nnyruteofhkegnom '@types/chai': 4.3.5 '@types/chai-as-promised': 7.1.5 '@types/mocha': 8.2.3 '@types/node': 18.17.1 - '@types/node-persist': 3.1.4 '@types/sinon': 10.0.16 chai: 4.3.7 chai-as-promised: 7.1.1_chai@4.3.7 @@ -692,6 +690,9 @@ packages: /@itwin/core-bentley/3.7.12: resolution: {integrity: sha1-UE6Q9Q1lxzH+/rtZ89WcN1ZYyqI=} + /@itwin/core-bentley/4.1.2: + resolution: {integrity: sha512-Pqr3FBcxMw9sbCPXU2RaXHRt5vIQLCZ0fYIQCqJ2QY7b5/xavD4FYkxrvQfEqCgZ3//XDmR2ggLKYldUgb2PDg==} + /@itwin/core-common/4.0.6_@itwin+core-bentley@3.7.12: resolution: {integrity: sha512-1N92kv3bqY/01Mdto/GCKgO5dG6dli9d06lp1KpHTUuwPpWVob1oIF/w5ij+0C4QvHq54SZlCxDfNaC7FH6lKQ==} peerDependencies: @@ -703,6 +704,17 @@ packages: js-base64: 3.7.5 dev: false + /@itwin/core-common/4.0.6_@itwin+core-bentley@4.1.2: + resolution: {integrity: sha512-1N92kv3bqY/01Mdto/GCKgO5dG6dli9d06lp1KpHTUuwPpWVob1oIF/w5ij+0C4QvHq54SZlCxDfNaC7FH6lKQ==} + peerDependencies: + '@itwin/core-bentley': ^4.0.6 + '@itwin/core-geometry': ^4.0.6 + dependencies: + '@itwin/core-bentley': 4.1.2 + flatbuffers: 1.12.0 + js-base64: 3.7.5 + dev: false + /@itwin/eslint-plugin/3.7.8_cgdknpc562nnyruteofhkegnom: resolution: {integrity: sha512-zPgGUZro3NZNH5CVCrzxy+Zyi0CucCMO3aYsPn8eaAvLQE1iqWt+M0XT+ih6FwZXRiHSrPhNrjTvP8cuFC96og==} hasBin: true @@ -2193,12 +2205,6 @@ packages: resolution: {integrity: sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==} dev: true - /@types/node-persist/3.1.4: - resolution: {integrity: sha512-MXwo/ijhPIIKa5jLxwBfs8wTVZzwO36V/a12TSzsm5hAMFiY9CgSzbFobvQEmQTRu778CIIhJoT59KF2BzSYwg==} - dependencies: - '@types/node': 18.17.1 - dev: true - /@types/node/16.18.39: resolution: {integrity: sha512-8q9ZexmdYYyc5/cfujaXb4YOucpQxAV4RMG0himLyDUOEr8Mr79VrqsFI+cQ2M2h89YIuy95lbxuYjxT4Hk4kQ==} dev: true @@ -2488,7 +2494,7 @@ packages: dev: true /ajv-formats/2.1.1: - resolution: {integrity: sha1-bmaUAGWet0lzu/LjMycYCgmWtSA=} + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependenciesMeta: ajv: optional: true @@ -2506,7 +2512,7 @@ packages: dev: true /ajv/8.12.0: - resolution: {integrity: sha1-0aBScyPiL1NWLFZ8AJkVd9++GdE=} + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 @@ -2683,6 +2689,13 @@ packages: engines: {node: '>=10.12.0'} dev: false + /atomically/2.0.2: + resolution: {integrity: sha512-Xfmb4q5QV7uqTlVdMSTtO5eF4DCHfNOdaPyKlbFShkzeNP+3lj3yjjcbdjSmEY4+pDBKJ9g26aP+ImTe88UHoQ==} + dependencies: + stubborn-fs: 1.2.5 + when-exit: 2.1.1 + dev: false + /available-typed-arrays/1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} @@ -3108,6 +3121,20 @@ packages: semver: 7.5.4 dev: false + /conf/11.0.2: + resolution: {integrity: sha512-jjyhlQ0ew/iwmtwsS2RaB6s8DBifcE2GYBEaw2SJDUY/slJJbNfY4GlDVzOs/ff8cM/Wua5CikqXgbFl5eu85A==} + engines: {node: '>=14.16'} + dependencies: + ajv: 8.12.0 + ajv-formats: 2.1.1 + atomically: 2.0.2 + debounce-fn: 5.1.2 + dot-prop: 7.2.0 + env-paths: 3.0.0 + json-schema-typed: 8.0.1 + semver: 7.5.4 + dev: false + /content-disposition/0.5.4: resolution: {integrity: sha1-i4K076yCUSoCuwsdzsnSxejrW/4=} engines: {node: '>= 0.6'} @@ -3274,6 +3301,13 @@ packages: mimic-fn: 3.1.0 dev: false + /debounce-fn/5.1.2: + resolution: {integrity: sha512-Sr4SdOZ4vw6eQDvPYNxHogvrxmCIld/VenC5JbNrFwMiwd7lY/Z18ZFfo+EWNG4DD9nFlAujWAo/wGuOPHmy5A==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: false + /debounce/1.2.1: resolution: {integrity: sha1-OIgdj0FmpcWEgCDBGCe4NLyz4KU=} dev: true @@ -3495,6 +3529,13 @@ packages: is-obj: 2.0.0 dev: false + /dot-prop/7.2.0: + resolution: {integrity: sha512-Ol/IPXUARn9CSbkrdV4VJo7uCy1I3VuSiWCaFSg+8BdUOzF9n3jefIpcgAydvUZbTdEBZs2vEiTiS9m61ssiDA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + type-fest: 2.19.0 + dev: false + /dotenv-expand/5.1.0: resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==} @@ -3589,6 +3630,11 @@ packages: resolution: {integrity: sha1-QgOZ1BbOH76bwKB8Yvpo1n/Q+PI=} engines: {node: '>=6'} + /env-paths/3.0.0: + resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + /error-ex/1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: @@ -5175,12 +5221,16 @@ packages: dev: true /json-schema-traverse/1.0.0: - resolution: {integrity: sha1-rnvLNlard6c7pcSb9lTzjmtoYOI=} + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} /json-schema-typed/7.0.3: resolution: {integrity: sha1-I/9IG4tO680soSO0+gQJ5mRpotk=} dev: false + /json-schema-typed/8.0.1: + resolution: {integrity: sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==} + dev: false + /json-stable-stringify-without-jsonify/1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true @@ -5679,6 +5729,11 @@ packages: engines: {node: '>=8'} dev: false + /mimic-fn/4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: false + /mimic-response/1.0.1: resolution: {integrity: sha1-SSNTiHju9CBjy4o+OweYeBSHqxs=} engines: {node: '>=4'} @@ -5914,11 +5969,6 @@ packages: dev: true optional: true - /node-persist/3.1.3: - resolution: {integrity: sha512-CaFv+kSZtsc+VeDRldK1yR47k1vPLBpzYB9re2z7LIwITxwBtljMq3s8VQnnr+x3E8pQfHbc5r2IyJsBLJhtXg==} - engines: {node: '>=10.12.0'} - dev: false - /node-preload/0.2.1: resolution: {integrity: sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==} engines: {node: '>=8'} @@ -6587,7 +6637,7 @@ packages: engines: {node: '>=0.10.0'} /require-from-string/2.0.2: - resolution: {integrity: sha1-iaf92TgmEmcxjq/hT5wy5ZjDaQk=} + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} /require-main-filename/2.0.0: @@ -7054,6 +7104,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + /stubborn-fs/1.2.5: + resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==} + dev: false + /subarg/1.0.0: resolution: {integrity: sha1-9izxdYHplrSPyWVpn1TAauJouNI=} dependencies: @@ -7233,7 +7287,7 @@ packages: dev: true /type-fest/0.13.1: - resolution: {integrity: sha1-AXLLW86AsL1ULqNI21DH4hg02TQ=} + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} engines: {node: '>=10'} dev: true optional: true @@ -7244,12 +7298,12 @@ packages: dev: true /type-fest/0.8.1: - resolution: {integrity: sha1-CeJJ696FHTseSNJ8EFREZn8XuD0=} + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} dev: true /type-fest/2.19.0: - resolution: {integrity: sha1-iAaAFbszA2pZi5UuVekxGmD9Ops=} + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} dev: false @@ -7460,6 +7514,10 @@ packages: webidl-conversions: 3.0.1 dev: false + /when-exit/2.1.1: + resolution: {integrity: sha512-XLipGldz/UcleuGaoQjbYuWwD+ICRnzIjlldtwTaTWr7aZz8yQW49rXk6MHQnh+KxOiWiJpM1vIyaxprOnlW4g==} + dev: false + /which-boxed-primitive/1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: