diff --git a/package.json b/package.json index 5e92c57d33c..4b588facc7f 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "@openapitools/openapi-generator-cli": "2.3.3", "@types/fs-extra": "9.0.11", "@types/jasminewd2": "2.0.10", + "@types/node": "15.14.7", "@types/node-fetch": "2.5.4", "@types/tape": "4.13.0", "@types/tape-promise": "4.0.1", diff --git a/packages/cactus-cmd-api-server/Dockerfile b/packages/cactus-cmd-api-server/Dockerfile index 39228aa64aa..3dae23f1148 100644 --- a/packages/cactus-cmd-api-server/Dockerfile +++ b/packages/cactus-cmd-api-server/Dockerfile @@ -50,8 +50,8 @@ EXPOSE 3000 4000 USER $APP_USER -RUN npm i @hyperledger/cactus-cmd-api-server@${NPM_PKG_VERSION} --production +RUN npm i @elenaizaguirre/cactus-cmd-api-server@${NPM_PKG_VERSION} ENTRYPOINT ["/sbin/tini", "--"] -CMD ["node", "node_modules/@hyperledger/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js"] +CMD ["node", "node_modules/@elenaizaguirre/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js"] HEALTHCHECK --interval=5s --timeout=5s --start-period=1s --retries=30 CMD /healthcheck.sh diff --git a/packages/cactus-cmd-api-server/package.json b/packages/cactus-cmd-api-server/package.json index b1cdd64e7ff..7e18883095b 100644 --- a/packages/cactus-cmd-api-server/package.json +++ b/packages/cactus-cmd-api-server/package.json @@ -87,10 +87,11 @@ "express-jwt": "6.0.0", "express-jwt-authz": "2.4.1", "express-openapi-validator": "3.10.0", + "fs-extra": "10.0.0", "http-status-codes": "2.1.4", "jose": "1.28.1", + "lmify": "0.3.0", "node-forge": "0.10.0", - "npm": "7.19.1", "prom-client": "13.1.0", "rxjs": "7.1.0", "semver": "7.3.2", @@ -111,7 +112,6 @@ "@types/jsonwebtoken": "8.5.1", "@types/multer": "1.4.5", "@types/node-forge": "0.9.3", - "@types/npm": "2.0.32", "@types/passport": "1.0.6", "@types/passport-oauth2": "1.4.10", "@types/passport-saml": "1.1.2", diff --git a/packages/cactus-cmd-api-server/src/main/typescript/api-server.ts b/packages/cactus-cmd-api-server/src/main/typescript/api-server.ts index c9f94af4cc7..ec25467f3b9 100644 --- a/packages/cactus-cmd-api-server/src/main/typescript/api-server.ts +++ b/packages/cactus-cmd-api-server/src/main/typescript/api-server.ts @@ -1,11 +1,13 @@ -import path from "path"; import type { AddressInfo } from "net"; +import type { Server as SecureServer } from "https"; +import os from "os"; +import path from "path"; import tls from "tls"; import { Server, createServer } from "http"; -import type { Server as SecureServer } from "https"; import { createServer as createSecureServer } from "https"; import { gte } from "semver"; -import npm from "npm"; +import lmify from "lmify"; +import fs from "fs-extra"; import expressHttpProxy from "express-http-proxy"; import type { Application, Request, Response, RequestHandler } from "express"; import express from "express"; @@ -41,7 +43,9 @@ import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter"; import { AuthorizerFactory } from "./authzn/authorizer-factory"; import { WatchHealthcheckV1 } from "./generated/openapi/typescript-axios"; import { WatchHealthcheckV1Endpoint } from "./web-services/watch-healthcheck-v1-endpoint"; +import { RuntimeError } from "run-time-error"; export interface IApiServerConstructorOptions { + pluginManagerOptions?: { pluginsPath: string }; pluginRegistry?: PluginRegistry; httpServerApi?: Server | SecureServer; wsServerApi?: SocketIoServer; @@ -71,6 +75,7 @@ export class ApiServer { private readonly wsApi: SocketIoServer; private readonly expressApi: Application; private readonly expressCockpit: Application; + private readonly pluginsPath: string; public prometheusExporter: PrometheusExporter; public get className(): string { @@ -127,6 +132,23 @@ export class ApiServer { label: "api-server", level: options.config.logLevel, }); + + const defaultPluginsPath = path.join( + os.tmpdir(), + "org", + "hyperledger", + "cactus", + "plugins", + ); + + const { pluginsPath } = { + ...{ pluginsPath: defaultPluginsPath }, + ...JSON.parse(this.options.config.pluginManagerOptionsJson), + ...this.options.pluginManagerOptions, + } as { pluginsPath: string }; + + this.pluginsPath = pluginsPath; + this.log.debug("pluginsPath: %o", pluginsPath); } public getPrometheusExporter(): PrometheusExporter { @@ -256,8 +278,16 @@ export class ApiServer { await this.installPluginPackage(pluginImport); + const packagePath = path.join( + this.pluginsPath, + options.instanceId, + "node_modules", + packageName, + ); + this.log.debug("Package path: %o", packagePath); + // eslint-disable-next-line @typescript-eslint/no-var-requires - const pluginPackage = require(/* webpackIgnore: true */ packageName); + const pluginPackage = require(/* webpackIgnore: true */ packagePath); const createPluginFactory = pluginPackage.createPluginFactory as PluginFactoryFactory; const pluginFactoryOptions: IPluginFactoryOptions = { @@ -276,54 +306,38 @@ export class ApiServer { const fnTag = `ApiServer#installPluginPackage()`; const { packageName: pkgName } = pluginImport; - const npmLogHandler = (message: unknown) => { - this.log.debug(`${fnTag} [npm-log]:`, message); - }; - - const cleanUpNpmLogHandler = () => { - npm.off("log", npmLogHandler); - }; - + const instanceId = pluginImport.options.instanceId; + const pluginPackageDir = path.join(this.pluginsPath, instanceId); try { - this.log.info(`Installing ${pkgName} for plugin import`, pluginImport); - npm.on("log", npmLogHandler); - - await new Promise((resolve, reject) => { - npm.load((err?: Error) => { - if (err) { - this.log.error(`${fnTag} npm load fail:`, err); - const { message, stack } = err; - reject(new Error(`${fnTag} npm load fail: ${message}: ${stack}`)); - } else { - // do not touch package.json - npm.config.set("save", false); - // do not touch package-lock.json - npm.config.set("package-lock", false); - // do not waste resources on running an audit - npm.config.set("audit", false); - // do not wast resources on rendering a progress bar - npm.config.set("progress", false); - resolve(); - } - }); - }); - - await new Promise((resolve, reject) => { - const npmInstallHandler = (errInstall?: Error, result?: unknown) => { - if (errInstall) { - this.log.error(`${fnTag} npm install failed:`, errInstall); - const { message: m, stack } = errInstall; - reject(new Error(`${fnTag} npm install fail: ${m}: ${stack}`)); - } else { - this.log.info(`Installed ${pkgName} OK`, result); - resolve(result); - } - }; - - npm.commands.install([pkgName], npmInstallHandler); - }); - } finally { - cleanUpNpmLogHandler(); + await fs.mkdirp(pluginPackageDir); + this.log.debug(`${pkgName} plugin package dir: %o`, pluginPackageDir); + } catch (ex) { + const errorMessage = + "Could not create plugin installation directory, check the file-system permissions."; + throw new RuntimeError(errorMessage, ex); + } + try { + lmify.setPackageManager("npm"); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + lmify.setRootDir(pluginPackageDir); + this.log.debug(`Installing ${pkgName} for plugin import`, pluginImport); + const out = await lmify.install([ + pkgName, + "--production", + "--audit=false", + "--progress=false", + "--fund=false", + `--prefix=${pluginPackageDir}`, + // "--ignore-workspace-root-check", + ]); + this.log.debug("%o install result: %o", pkgName, out); + if (out.exitCode !== 0) { + throw new RuntimeError("Non-zero exit code: ", JSON.stringify(out)); + } + this.log.info(`Installed ${pkgName} OK`); + } catch (ex) { + throw new RuntimeError(`${fnTag} plugin install fail: ${pkgName}`, ex); } } diff --git a/packages/cactus-cmd-api-server/src/main/typescript/config/config-service.ts b/packages/cactus-cmd-api-server/src/main/typescript/config/config-service.ts index ebabfed631c..25a6e632bfc 100644 --- a/packages/cactus-cmd-api-server/src/main/typescript/config/config-service.ts +++ b/packages/cactus-cmd-api-server/src/main/typescript/config/config-service.ts @@ -26,6 +26,7 @@ convict.addFormat(FORMAT_PLUGIN_ARRAY); convict.addFormat(ipaddress); export interface ICactusApiServerOptions { + pluginManagerOptionsJson: string; authorizationProtocol: AuthorizationProtocol; authorizationConfigJson: IAuthorizationConfig; configFile: string; @@ -88,6 +89,14 @@ export class ConfigService { private static getConfigSchema(): Schema { return { + pluginManagerOptionsJson: { + doc: + "Can be used to override npm registry and authentication details for example. See https://www.npmjs.com/package/live-plugin-manager#pluginmanagerconstructoroptions-partialpluginmanageroptions for further details.", + format: "*", + default: "{}", + env: "PLUGIN_MANAGER_OPTIONS_JSON", + arg: "plugin-manager-options-json", + }, authorizationProtocol: { doc: "The name of the authorization protocol to use. Accepted values" + @@ -518,6 +527,7 @@ export class ConfigService { }; return { + pluginManagerOptionsJson: "{}", authorizationProtocol: AuthorizationProtocol.JSON_WEB_TOKEN, authorizationConfigJson, configFile: ".config.json", diff --git a/packages/cactus-cmd-api-server/src/test/typescript/benchmark/artillery-api-benchmark.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/benchmark/artillery-api-benchmark.test.ts index cb2598037f4..16e4393ab0c 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/benchmark/artillery-api-benchmark.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/benchmark/artillery-api-benchmark.test.ts @@ -1,3 +1,9 @@ +import { promisify } from "util"; +import { unlinkSync, readFileSync } from "fs"; + +import { exec } from "child_process"; +import path from "path"; + import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import { JWK } from "jose"; @@ -23,11 +29,6 @@ const log = LoggerProvider.getOrCreate({ label: "logger-test", }); -import { promisify } from "util"; -import { unlinkSync, readFileSync } from "fs"; - -import { exec } from "child_process"; - const shell_exec = promisify(exec); const artilleryScriptLocation = @@ -47,9 +48,18 @@ test("Start API server, and run Artillery benchmark test.", async (t: Test) => { log.info("Generating Config..."); + const pluginsPath = path.join( + __dirname, // start at the current file's path + "../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/artillery-api-benchmark_test", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + const configService = new ConfigService(); const apiServerOptions = configService.newExampleConfig(); apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; apiServerOptions.configFile = ""; apiServerOptions.apiCorsDomainCsv = "*"; apiServerOptions.apiPort = 4000; diff --git a/packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts index d28d3e92479..1bafbf5cd23 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts @@ -1,3 +1,4 @@ +import path from "path"; import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import { JWK, JWT } from "jose"; @@ -64,9 +65,18 @@ test(testCase, async (t: Test) => { }, }; + const pluginsPath = path.join( + __dirname, // start at the current file's path + "../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/jwt-endpoint-authorization_test", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + const configService = new ConfigService(); const apiSrvOpts = configService.newExampleConfig(); apiSrvOpts.authorizationProtocol = AuthorizationProtocol.JSON_WEB_TOKEN; + apiSrvOpts.pluginManagerOptionsJson = pluginManagerOptionsJson; apiSrvOpts.authorizationConfigJson = authorizationConfig; apiSrvOpts.configFile = ""; apiSrvOpts.apiCorsDomainCsv = "*"; diff --git a/packages/cactus-cmd-api-server/src/test/typescript/integration/remote-plugin-imports.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/integration/remote-plugin-imports.test.ts index 9a186ea1ab4..cf7935ead7d 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/integration/remote-plugin-imports.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/integration/remote-plugin-imports.test.ts @@ -17,6 +17,7 @@ import { import { DefaultApi } from "@hyperledger/cactus-plugin-keychain-vault"; import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; +import path from "path"; test("NodeJS API server + Rust plugin work together", async (t: Test) => { const vaultTestContainer = new VaultTestServer({}); @@ -57,9 +58,18 @@ test("NodeJS API server + Rust plugin work together", async (t: Test) => { }); const apiClient = new DefaultApi(configuration); + const pluginsPath = path.join( + __dirname, // start at the current file's path + "../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/remote-plugin-imports_test", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + const configService = new ConfigService(); const apiServerOptions = configService.newExampleConfig(); apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; apiServerOptions.configFile = ""; apiServerOptions.apiCorsDomainCsv = "*"; apiServerOptions.apiPort = 0; diff --git a/packages/cactus-cmd-api-server/src/test/typescript/unit/config/config-service-example-config-validity.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/config/config-service-example-config-validity.test.ts index 3236c7f53ff..e4a1df25ed9 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/unit/config/config-service-example-config-validity.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/config/config-service-example-config-validity.test.ts @@ -1,17 +1,29 @@ -import { LoggerProvider } from "@hyperledger/cactus-common"; +import path from "path"; import test, { Test } from "tape-promise/tape"; +import { v4 as uuidv4 } from "uuid"; +import { LoggerProvider } from "@hyperledger/cactus-common"; import { IAuthorizationConfig } from "../../../../main/typescript/public-api"; import { ApiServer } from "../../../../main/typescript/public-api"; import { ConfigService } from "../../../../main/typescript/public-api"; test("Generates valid example config for the API server", async (t: Test) => { + const pluginsPath = path.join( + __dirname, + "../../../../../../", // walk back up to the project root + ".tmp/test/test-cmd-api-server/config-service-example-config-validity_test/", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + const configService = new ConfigService(); t.ok(configService, "Instantiated ConfigService truthy OK"); const exampleConfig = configService.newExampleConfig(); t.ok(exampleConfig, "configService.newExampleConfig() truthy OK"); + exampleConfig.pluginManagerOptionsJson = pluginManagerOptionsJson; + // FIXME - this hack should not be necessary, we need to re-think how we // do configuration parsing. The convict library may not be the path forward. exampleConfig.authorizationConfigJson = (JSON.stringify( diff --git a/packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts similarity index 66% rename from packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts rename to packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts index 72189e16538..94cdc17b5a0 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts @@ -1,3 +1,4 @@ +import path from "path"; import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import { JWK } from "jose"; @@ -9,21 +10,25 @@ import { ConsortiumDatabase, ICactusPlugin, Configuration, + IPluginConsortium, } from "@hyperledger/cactus-core-api"; import { ApiServer, AuthorizationProtocol, ConfigService, -} from "../../../main/typescript/public-api"; +} from "../../../../main/typescript/public-api"; -import { K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS } from "../../../main/typescript/prometheus-exporter/metrics"; +import { K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS } from "../../../../main/typescript/prometheus-exporter/metrics"; -import { DefaultApi as ApiServerApi } from "../../../main/typescript/public-api"; +import { DefaultApi as ApiServerApi } from "../../../../main/typescript/public-api"; const logLevel: LogLevelDesc = "TRACE"; -test("can instal plugins at runtime based on imports", async (t: Test) => { +test("can install plugin-consortium-manual", async (t: Test) => { + const keychainId = uuidv4(); + const consortiumPluginInstanceId = uuidv4(); + // Adding a new plugin to update the prometheus metric K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS const keyPair = await JWK.generate("EC", "secp256k1", { use: "sig" }, true); const keyPairPem = keyPair.toPEM(true); @@ -35,8 +40,20 @@ test("can instal plugins at runtime based on imports", async (t: Test) => { pluginInstance: [], }; + const pluginsPath = path.join( + __dirname, // start at the current file's path + "../../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/plugin-import-with-npm-install_test", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const configService = new ConfigService(); + const apiServerOptions = configService.newExampleConfig(); + const pluginManagerOptions = { pluginsPath }; + const pluginManagerOptionsJson = JSON.stringify(pluginManagerOptions); + + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; apiServerOptions.configFile = ""; apiServerOptions.apiCorsDomainCsv = "*"; @@ -49,7 +66,7 @@ test("can instal plugins at runtime based on imports", async (t: Test) => { type: PluginImportType.Local, options: { instanceId: uuidv4(), - keychainId: uuidv4(), + keychainId, logLevel, }, }, @@ -57,7 +74,7 @@ test("can instal plugins at runtime based on imports", async (t: Test) => { packageName: "@hyperledger/cactus-plugin-consortium-manual", type: PluginImportType.Local, options: { - instanceId: uuidv4(), + instanceId: consortiumPluginInstanceId, keyPairPem: keyPairPem, consortiumDatabase: db, }, @@ -69,11 +86,10 @@ test("can instal plugins at runtime based on imports", async (t: Test) => { config: config.getProperties(), }); + test.onFinish(() => apiServer.shutdown()); + const startResponse = apiServer.start(); - await t.doesNotReject( - startResponse, - "failed to start API server with dynamic plugin imports configured for it...", - ); + await t.doesNotReject(startResponse, "started API server OK"); t.ok(startResponse, "startResponse truthy OK"); const addressInfoApi = (await startResponse).addressInfoApi; @@ -141,5 +157,38 @@ test("can instal plugins at runtime based on imports", async (t: Test) => { // e.g. remove the dummy plugin instance we just pushed pluginRegistry.plugins.pop(); - test.onFinish(() => apiServer.shutdown()); + const keychain = pluginRegistry.findOneByKeychainId(keychainId); + + const hasX1 = await keychain.has("x"); + t.false(hasX1, "hasX1 === false OK"); + + await keychain.set("x", "y"); + + const hasX2 = await keychain.has("x"); + t.true(hasX2, "hasX2 === true OK"); + + type DummyConsortiumPlugin = IPluginConsortium< + unknown, + unknown, + unknown, + unknown + >; + + // TODO - use the new getOneById implementation once + // https://github.com/hyperledger/cactus/issues/1197 + // has been resolved + const consortiumPlugin = pluginRegistry + .getPlugins() + .find( + (it) => it.getInstanceId() === consortiumPluginInstanceId, + ) as DummyConsortiumPlugin; + + t.ok(consortiumPlugin, "consortiumPlugin located via instance ID truthy OK"); + + // FIXME - uncomment this once https://github.com/hyperledger/cactus/issues/1199 + // has been resolved (and also published to npm) + // const nodeJwsRes = await consortiumPlugin.getNodeJws({}); + // t.ok(nodeJwsRes, "nodeJwsRes truthy OK"); + + t.end(); }); diff --git a/packages/cactus-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts similarity index 73% rename from packages/cactus-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts rename to packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts index 18e5e3eea6f..10faffb68ea 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts @@ -9,18 +9,32 @@ import { ApiServer, AuthorizationProtocol, ConfigService, -} from "../../../main/typescript/public-api"; +} from "../../../../main/typescript/public-api"; -import { K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS } from "../../../main/typescript/prometheus-exporter/metrics"; +import { K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS } from "../../../../main/typescript/prometheus-exporter/metrics"; -import { DefaultApi as ApiServerApi } from "../../../main/typescript/public-api"; +import { DefaultApi as ApiServerApi } from "../../../../main/typescript/public-api"; +import path from "path"; const logLevel: LogLevelDesc = "TRACE"; test("can import plugins at runtime (CLI)", async (t: Test) => { + // const pluginsPath = path.join( + // "/tmp/org/hyperledger/cactus/cmd-api-server/install-basic-plugin-keychain-memory_test", // the dir path from the root + // uuidv4(), // then a random directory to ensure proper isolation + // ); + const pluginsPath = path.join( + __dirname, // start at the current file's path + "../../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/runtime-plugin-imports_test", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + const configService = new ConfigService(); const apiServerOptions = configService.newExampleConfig(); apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; apiServerOptions.configFile = ""; apiServerOptions.apiCorsDomainCsv = "*"; apiServerOptions.apiPort = 0; diff --git a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts new file mode 100644 index 00000000000..5e0539d7a89 --- /dev/null +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts @@ -0,0 +1,98 @@ +import test, { Test } from "tape-promise/tape"; +import { v4 as uuidv4 } from "uuid"; + +import { LogLevelDesc } from "@hyperledger/cactus-common"; + +import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; + +import { + ApiServer, + AuthorizationProtocol, + ConfigService, +} from "../../../../main/typescript/public-api"; + +import { K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS } from "../../../../main/typescript/prometheus-exporter/metrics"; + +import { DefaultApi as ApiServerApi } from "../../../../main/typescript/public-api"; +import path from "path"; + +const logLevel: LogLevelDesc = "TRACE"; + +test("can install plugin-ledger-connector-fabric", async (t: Test) => { + const pluginsPath = path.join( + __dirname, // start at the current file's path + "../../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/runtime-plugin-imports_test", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ + pluginsPath, + npmInstallMode: "noCache", + }); + + const configService = new ConfigService(); + const apiServerOptions = configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = 0; + apiServerOptions.cockpitPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.plugins = [ + { + packageName: "@hyperledger/cactus-plugin-ledger-connector-fabric", + type: PluginImportType.Local, + options: { + instanceId: uuidv4(), + logLevel, + connectionProfile: {}, + peerBinary: "peer", + }, + }, + ]; + const config = configService.newExampleConfigConvict(apiServerOptions); + + const apiServer = new ApiServer({ + config: config.getProperties(), + }); + + test.onFinish(() => apiServer.shutdown()); + + const startResponse = apiServer.start(); + await t.doesNotReject(startResponse, "started API server dynamic imports OK"); + t.ok(startResponse, "startResponse truthy OK"); + + const addressInfoApi = (await startResponse).addressInfoApi; + const protocol = apiServerOptions.apiTlsEnabled ? "https" : "http"; + const { address, port } = addressInfoApi; + const apiHost = `${protocol}://${address}:${port}`; + t.comment( + `Metrics URL: ${apiHost}/api/v1/api-server/get-prometheus-exporter-metrics`, + ); + + const apiConfig = new Configuration({ basePath: apiHost }); + const apiClient = new ApiServerApi(apiConfig); + + { + const res = await apiClient.getPrometheusMetricsV1(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + " Total number of plugins imported\n" + + "# TYPE " + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + " gauge\n" + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + '{type="' + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + '"} 1'; + t.ok(res); + t.ok(res.data); + t.equal(res.status, 200); + t.true( + res.data.includes(promMetricsOutput), + "Total 1 plugins imported as expected. RESULT OK", + ); + } +}); diff --git a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts new file mode 100644 index 00000000000..b1ff5284658 --- /dev/null +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts @@ -0,0 +1,102 @@ +import path from "path"; +import test, { Test } from "tape-promise/tape"; +import { v4 as uuidv4 } from "uuid"; + +import { LogLevelDesc } from "@hyperledger/cactus-common"; + +import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; + +import { + ApiServer, + AuthorizationProtocol, + ConfigService, +} from "../../../../main/typescript/public-api"; + +import { K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS } from "../../../../main/typescript/prometheus-exporter/metrics"; + +import { DefaultApi as ApiServerApi } from "../../../../main/typescript/public-api"; + +const logLevel: LogLevelDesc = "TRACE"; + +test("can import plugins at runtime (CLI)", async (t: Test) => { + // const pluginsPath = path.join( + // "/tmp/org/hyperledger/cactus/cmd-api-server/runtime-plugin-imports_test", // the dir path from the root + // uuidv4(), // then a random directory to ensure proper isolation + // ); + + const pluginsPath = path.join( + __dirname, // start at the current file's path + "../../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/install-basic-plugin-ledger-connector-quorum-0-7-0_test", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ + pluginsPath, + npmInstallMode: "noCache", + }); + + const configService = new ConfigService(); + const apiServerOptions = configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = 0; + apiServerOptions.cockpitPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.plugins = [ + { + packageName: "@hyperledger/cactus-plugin-ledger-connector-quorum", + type: PluginImportType.Local, + options: { + instanceId: uuidv4(), + logLevel, + rpcApiHttpHost: "localhost:8545", + }, + }, + ]; + const config = configService.newExampleConfigConvict(apiServerOptions); + + const apiServer = new ApiServer({ + config: config.getProperties(), + }); + + const startResponse = apiServer.start(); + await t.doesNotReject(startResponse, "started API server dynamic imports OK"); + t.ok(startResponse, "startResponse truthy OK"); + + const addressInfoApi = (await startResponse).addressInfoApi; + const protocol = apiServerOptions.apiTlsEnabled ? "https" : "http"; + const { address, port } = addressInfoApi; + const apiHost = `${protocol}://${address}:${port}`; + t.comment( + `Metrics URL: ${apiHost}/api/v1/api-server/get-prometheus-exporter-metrics`, + ); + + const apiConfig = new Configuration({ basePath: apiHost }); + const apiClient = new ApiServerApi(apiConfig); + + { + const res = await apiClient.getPrometheusMetricsV1(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + " Total number of plugins imported\n" + + "# TYPE " + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + " gauge\n" + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + '{type="' + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + '"} 1'; + t.ok(res); + t.ok(res.data); + t.equal(res.status, 200); + t.true( + res.data.includes(promMetricsOutput), + "Total 1 plugins imported as expected. RESULT OK", + ); + } + + test.onFinish(() => apiServer.shutdown()); +}); diff --git a/packages/cactus-cmd-api-server/tsconfig.json b/packages/cactus-cmd-api-server/tsconfig.json index fa0088d7d22..58fc8e3360c 100644 --- a/packages/cactus-cmd-api-server/tsconfig.json +++ b/packages/cactus-cmd-api-server/tsconfig.json @@ -5,6 +5,7 @@ "outDir": "./dist/lib/", "declarationDir": "dist/lib", "rootDir": "./src", + "skipLibCheck": true, "tsBuildInfoFile": "../../.build-cache/cactus-cmd-api-server.tsbuildinfo" }, "include": [ diff --git a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts index 21c3fdba685..d5fde643018 100644 --- a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts +++ b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts @@ -1,3 +1,4 @@ +import path from "path"; import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import { JWK } from "jose"; @@ -29,8 +30,18 @@ test("can instal plugins at runtime based on imports", async (t: Test) => { pluginInstance: [], }; + const pluginsPath = path.join( + __dirname, + "../../../../../../", // walk back up to the project root + ".tmp/test/test-cmd-api-server/plugin-import-with-npm-install_test/", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + const configService = new ConfigService(); + const apiServerOptions = configService.newExampleConfig(); + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; apiServerOptions.configFile = ""; apiServerOptions.apiCorsDomainCsv = "*"; diff --git a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts index 670887b0df5..6879c9c0f00 100644 --- a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts +++ b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts @@ -1,3 +1,4 @@ +import path from "path"; import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; @@ -13,11 +14,18 @@ import { PluginImportType } from "@hyperledger/cactus-core-api"; const logLevel: LogLevelDesc = "TRACE"; test("can import plugins at runtime (CLI)", async (t: Test) => { - // const pluginRegistry = new PluginRegistry({ plugins: [] }); + const pluginsPath = path.join( + __dirname, // start at the current file's path + "../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/runtime-plugin-imports_test", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); const configService = new ConfigService(); const apiServerOptions = configService.newExampleConfig(); apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; apiServerOptions.configFile = ""; apiServerOptions.apiCorsDomainCsv = "*"; apiServerOptions.apiPort = 0; diff --git a/yarn.lock b/yarn.lock index 328e064a9b9..800224b9166 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2780,68 +2780,12 @@ safe-buffer "^5.1.1" util.promisify "^1.0.0" -"@npmcli/arborist@^2.3.0", "@npmcli/arborist@^2.5.0", "@npmcli/arborist@^2.6.4": - version "2.7.1" - resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-2.7.1.tgz#dc7b8a75d7469c26559675adbccae26cfcbe2d01" - integrity sha512-EGDHJs6dna/52BrStr/6aaRcMLrYxGbSjT4V3JzvoTBY9/w5i2+1KNepmsG80CAsGADdo6nuNnFwb7sDRm8ZAw== - dependencies: - "@npmcli/installed-package-contents" "^1.0.7" - "@npmcli/map-workspaces" "^1.0.2" - "@npmcli/metavuln-calculator" "^1.1.0" - "@npmcli/move-file" "^1.1.0" - "@npmcli/name-from-folder" "^1.0.1" - "@npmcli/node-gyp" "^1.0.1" - "@npmcli/package-json" "^1.0.1" - "@npmcli/run-script" "^1.8.2" - bin-links "^2.2.1" - cacache "^15.0.3" - common-ancestor-path "^1.0.1" - json-parse-even-better-errors "^2.3.1" - json-stringify-nice "^1.1.4" - mkdirp "^1.0.4" - mkdirp-infer-owner "^2.0.0" - npm-install-checks "^4.0.0" - npm-package-arg "^8.1.0" - npm-pick-manifest "^6.1.0" - npm-registry-fetch "^11.0.0" - pacote "^11.2.6" - parse-conflict-json "^1.1.1" - proc-log "^1.0.0" - promise-all-reject-late "^1.0.0" - promise-call-limit "^1.0.1" - read-package-json-fast "^2.0.2" - readdir-scoped-modules "^1.1.0" - rimraf "^3.0.2" - semver "^7.3.5" - ssri "^8.0.1" - tar "^6.1.0" - treeverse "^1.0.4" - walk-up-path "^1.0.0" - -"@npmcli/ci-detect@^1.0.0", "@npmcli/ci-detect@^1.2.0", "@npmcli/ci-detect@^1.3.0": +"@npmcli/ci-detect@^1.0.0": version "1.3.0" resolved "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.3.0.tgz" integrity sha512-oN3y7FAROHhrAt7Rr7PnTSwrHrZVRTS2ZbyxeQwSSYD0ifwM3YNgQqbaRmjcWoPyq77MjchusjJDspbzMmip1Q== -"@npmcli/config@^2.2.0": - version "2.2.0" - resolved "https://registry.npmjs.org/@npmcli/config/-/config-2.2.0.tgz" - integrity sha512-y0V3F7RCWXy8kBOvKvKSRUNKRobLB6vL/UNchy/6+IUNIqu+UyrY3Z7jvj1ZA/AkYc/0WkCUtppCo+bPhMU8Aw== - dependencies: - ini "^2.0.0" - mkdirp-infer-owner "^2.0.0" - nopt "^5.0.0" - semver "^7.3.4" - walk-up-path "^1.0.0" - -"@npmcli/disparity-colors@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@npmcli/disparity-colors/-/disparity-colors-1.0.1.tgz" - integrity sha512-kQ1aCTTU45mPXN+pdAaRxlxr3OunkyztjbbxDY/aIcPS5CnCUrx+1+NvA6pTcYR7wmLZe37+Mi5v3nfbwPxq3A== - dependencies: - ansi-styles "^4.3.0" - -"@npmcli/git@^2.0.1", "@npmcli/git@^2.0.7", "@npmcli/git@^2.1.0": +"@npmcli/git@^2.0.1", "@npmcli/git@^2.1.0": version "2.1.0" resolved "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz" integrity sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw== @@ -2855,7 +2799,7 @@ semver "^7.3.5" which "^2.0.2" -"@npmcli/installed-package-contents@^1.0.6", "@npmcli/installed-package-contents@^1.0.7": +"@npmcli/installed-package-contents@^1.0.6": version "1.0.7" resolved "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz" integrity sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw== @@ -2863,26 +2807,7 @@ npm-bundled "^1.1.1" npm-normalize-package-bin "^1.0.1" -"@npmcli/map-workspaces@^1.0.2": - version "1.0.3" - resolved "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.3.tgz" - integrity sha512-SdlRlOoQw4WKD4vtb/n5gUkobEABYBEOo8fRE4L8CtBkyWDSvIrReTfKvQ/Jc/LQqDaaZ5iv1iMSQzKCUr1n1A== - dependencies: - "@npmcli/name-from-folder" "^1.0.1" - glob "^7.1.6" - minimatch "^3.0.4" - read-package-json-fast "^2.0.1" - -"@npmcli/metavuln-calculator@^1.1.0": - version "1.1.1" - resolved "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-1.1.1.tgz" - integrity sha512-9xe+ZZ1iGVaUovBVFI9h3qW+UuECUzhvZPxK9RaEA2mjU26o5D0JloGYWwLYvQELJNmBdQB6rrpuN8jni6LwzQ== - dependencies: - cacache "^15.0.5" - pacote "^11.1.11" - semver "^7.3.2" - -"@npmcli/move-file@^1.0.1", "@npmcli/move-file@^1.1.0": +"@npmcli/move-file@^1.0.1": version "1.1.2" resolved "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz" integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== @@ -2890,23 +2815,11 @@ mkdirp "^1.0.4" rimraf "^3.0.2" -"@npmcli/name-from-folder@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz" - integrity sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA== - -"@npmcli/node-gyp@^1.0.1", "@npmcli/node-gyp@^1.0.2": +"@npmcli/node-gyp@^1.0.2": version "1.0.2" resolved "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.2.tgz" integrity sha512-yrJUe6reVMpktcvagumoqD9r08fH1iRo01gn1u0zoCApa9lnZGEigVKUd2hzsCId4gdtkZZIVscLhNxMECKgRg== -"@npmcli/package-json@^1.0.1": - version "1.0.1" - resolved "https://registry.npmjs.org/@npmcli/package-json/-/package-json-1.0.1.tgz" - integrity sha512-y6jnu76E9C23osz8gEMBayZmaZ69vFOIk8vR1FJL/wbEJ54+9aVG9rLTjQKSXfgYZEr50nw1txBBFfBZZe+bYg== - dependencies: - json-parse-even-better-errors "^2.3.1" - "@npmcli/promise-spawn@^1.2.0", "@npmcli/promise-spawn@^1.3.2": version "1.3.2" resolved "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz" @@ -2914,7 +2827,7 @@ dependencies: infer-owner "^1.0.4" -"@npmcli/run-script@^1.8.2", "@npmcli/run-script@^1.8.3", "@npmcli/run-script@^1.8.4", "@npmcli/run-script@^1.8.5": +"@npmcli/run-script@^1.8.2": version "1.8.5" resolved "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.5.tgz" integrity sha512-NQspusBCpTjNwNRFMtz2C5MxoxyzlbuJ4YEhxAKrIonTiirKDtatsZictx9RgamQIx6+QuHMNmPl0wQdoESs9A== @@ -3668,6 +3581,11 @@ resolved "https://registry.npmjs.org/@types/node/-/node-12.11.1.tgz" integrity sha512-TJtwsqZ39pqcljJpajeoofYRfeZ7/I/OMUQ5pR4q5wOKf2ocrUvBAZUMhWsOvKx3dVc/aaV5GluBivt0sWqA5A== +"@types/node@15.14.7": + version "15.14.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.14.7.tgz#29fea9a5b14e2b75c19028e1c7a32edd1e89fe92" + integrity sha512-FA45p37/mLhpebgbPWWCKfOisTjxGK9lwcHlJ6XVLfu3NgfcazOJHdYUZCWPMK8QX4LhNZdmfo6iMz9FqpUbaw== + "@types/node@>=12.12.47": version "16.4.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.0.tgz#2c219eaa3b8d1e4d04f4dd6e40bc68c7467d5272" @@ -3688,13 +3606,6 @@ resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== -"@types/npm@2.0.32": - version "2.0.32" - resolved "https://registry.npmjs.org/@types/npm/-/npm-2.0.32.tgz" - integrity sha512-9Lg4woNVzJCtac0lET91H65lbO+8YXfk0nmlmoPGhHXMdaVEDloH6zOPIYMy2n39z/aCXXQR0nax66EDekAyIQ== - dependencies: - "@types/node" "*" - "@types/oauth@*": version "0.9.1" resolved "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.1.tgz" @@ -4236,7 +4147,7 @@ abab@^2.0.5: resolved "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== -abbrev@1, abbrev@~1.1.1: +abbrev@1: version "1.1.1" resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== @@ -4486,7 +4397,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.3.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -4498,11 +4409,6 @@ ansicolors@~0.3.2: resolved "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz" integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= -ansistyles@~0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/ansistyles/-/ansistyles-0.1.3.tgz" - integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk= - any-observable@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz" @@ -4564,7 +4470,7 @@ aproba@^2.0.0: resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== -archy@^1.0.0, archy@~1.0.0: +archy@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= @@ -5104,24 +5010,12 @@ bignumber.js@^9.0.0: resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz" integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== -bin-links@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/bin-links/-/bin-links-2.2.1.tgz" - integrity sha512-wFzVTqavpgCCYAh8SVBdnZdiQMxTkGR+T3b14CNpBXIBe2neJWaMGAZ55XWWHELJJ89dscuq0VCBqcVaIOgCMg== - dependencies: - cmd-shim "^4.0.1" - mkdirp "^1.0.3" - npm-normalize-package-bin "^1.0.0" - read-cmd-shim "^2.0.0" - rimraf "^3.0.0" - write-file-atomic "^3.0.3" - binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== -binary-extensions@^2.0.0, binary-extensions@^2.2.0: +binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== @@ -5575,7 +5469,7 @@ byline@^5.0.0: resolved "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz" integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= -byte-size@^7.0.0, byte-size@^7.0.1: +byte-size@^7.0.0: version "7.0.1" resolved "https://registry.npmjs.org/byte-size/-/byte-size-7.0.1.tgz" integrity sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A== @@ -5590,7 +5484,7 @@ bytes@3.1.0: resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@15.2.0, cacache@^15.0.3, cacache@^15.0.5, cacache@^15.2.0: +cacache@15.2.0, cacache@^15.0.5, cacache@^15.2.0: version "15.2.0" resolved "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz" integrity sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw== @@ -5960,12 +5854,10 @@ ci-info@^2.0.0: resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -cidr-regex@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/cidr-regex/-/cidr-regex-3.1.1.tgz" - integrity sha512-RBqYd32aDwbCMFJRL6wHOlDNYJsPNTt8vC82ErHF5vKt8QQzxm1FrkW8s/R5pVrXMf17sba09Uoy91PKiddAsw== - dependencies: - ip-regex "^4.1.0" +ci-info@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" + integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== cids@^0.7.1: version "0.7.5" @@ -6039,14 +5931,6 @@ cli-boxes@^2.2.0: resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== -cli-columns@^3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/cli-columns/-/cli-columns-3.1.2.tgz" - integrity sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4= - dependencies: - string-width "^2.0.0" - strip-ansi "^3.0.1" - cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz" @@ -6071,16 +5955,6 @@ cli-spinners@^2.5.0: resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz" integrity sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q== -cli-table3@^0.6.0: - version "0.6.0" - resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz" - integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ== - dependencies: - object-assign "^4.1.0" - string-width "^4.2.0" - optionalDependencies: - colors "^1.1.2" - cli-truncate@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz" @@ -6151,7 +6025,7 @@ clone@^1.0.2: resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -cmd-shim@^4.0.1, cmd-shim@^4.1.0: +cmd-shim@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/cmd-shim/-/cmd-shim-4.1.0.tgz" integrity sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw== @@ -6251,12 +6125,12 @@ colors@1.0.x: resolved "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz" integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= -colors@^1.1.2, colors@^1.4.0: +colors@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -columnify@^1.5.4, columnify@~1.5.4: +columnify@^1.5.4: version "1.5.4" resolved "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz" integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= @@ -6336,11 +6210,6 @@ comment-json@^4.1.0: has-own-prop "^2.0.0" repeat-string "^1.6.1" -common-ancestor-path@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz" - integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" @@ -7693,11 +7562,6 @@ diff@^4.0.1, diff@^4.0.2: resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" @@ -10505,7 +10369,7 @@ hosted-git-info@^2.1.4: resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== -hosted-git-info@^4.0.0, hosted-git-info@^4.0.1, hosted-git-info@^4.0.2: +hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz" integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== @@ -10927,7 +10791,7 @@ ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -init-package-json@^2.0.2, init-package-json@^2.0.3: +init-package-json@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/init-package-json/-/init-package-json-2.0.3.tgz" integrity sha512-tk/gAgbMMxR6fn1MgMaM1HpU1ryAmBWWitnxG5OhuNXeX0cbpbgV5jA4AIpQJVNoyOfOevTtO6WX+rPs+EFqaQ== @@ -11103,7 +10967,7 @@ ip-regex@^2.1.0: resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz" integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= -ip-regex@^4.0.0, ip-regex@^4.1.0: +ip-regex@^4.0.0: version "4.3.0" resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz" integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== @@ -11375,13 +11239,6 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-cidr@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/is-cidr/-/is-cidr-4.0.2.tgz" - integrity sha512-z4a1ENUajDbEl/Q6/pVBpTR1nBjjEE1X7qb7bmWYanNnPoKAvUCPFKeXV6Fe4mgTkWKBqiHIcwsI3SndiO5FeA== - dependencies: - cidr-regex "^3.1.1" - is-circular@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/is-circular/-/is-circular-1.0.2.tgz" @@ -12251,7 +12108,7 @@ json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: +json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -12297,11 +12154,6 @@ json-stable-stringify@1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-nice@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz" - integrity sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw== - json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" @@ -12421,16 +12273,6 @@ jszip@^3.1.3: readable-stream "~2.3.6" set-immediate-shim "~1.0.1" -just-diff-apply@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-3.0.0.tgz" - integrity sha512-K2MLc+ZC2DVxX4V61bIKPeMUUfj1YYZ3h0myhchDXOW1cKoPZMnjIoNCqv9bF2n5Oob1PFxuR2gVJxkxz4e58w== - -just-diff@^3.0.1: - version "3.1.1" - resolved "https://registry.npmjs.org/just-diff/-/just-diff-3.1.1.tgz" - integrity sha512-sdMWKjRq8qWZEjDcVA6llnUT8RDEBIfOiGpYFPYa9u+2c39JCsejktSP7mj5eRid5EIvTzIpQ2kDOCw1Nq9BjQ== - jwa@^1.4.1: version "1.4.1" resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz" @@ -12881,11 +12723,6 @@ levelup@^3.0.0: level-iterator-stream "~3.0.0" xtend "~4.0.0" -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - levn@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" @@ -12902,7 +12739,7 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -libnpmaccess@^4.0.1, libnpmaccess@^4.0.2: +libnpmaccess@^4.0.1: version "4.0.3" resolved "https://registry.npmjs.org/libnpmaccess/-/libnpmaccess-4.0.3.tgz" integrity sha512-sPeTSNImksm8O2b6/pf3ikv4N567ERYEpeKRPSmqlNt1dTZbvgpJIzg5vAhXHpw2ISBsELFRelk0jEahj1c6nQ== @@ -12912,70 +12749,7 @@ libnpmaccess@^4.0.1, libnpmaccess@^4.0.2: npm-package-arg "^8.1.2" npm-registry-fetch "^11.0.0" -libnpmdiff@^2.0.4: - version "2.0.4" - resolved "https://registry.npmjs.org/libnpmdiff/-/libnpmdiff-2.0.4.tgz" - integrity sha512-q3zWePOJLHwsLEUjZw3Kyu/MJMYfl4tWCg78Vl6QGSfm4aXBUSVzMzjJ6jGiyarsT4d+1NH4B1gxfs62/+y9iQ== - dependencies: - "@npmcli/disparity-colors" "^1.0.1" - "@npmcli/installed-package-contents" "^1.0.7" - binary-extensions "^2.2.0" - diff "^5.0.0" - minimatch "^3.0.4" - npm-package-arg "^8.1.1" - pacote "^11.3.0" - tar "^6.1.0" - -libnpmexec@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/libnpmexec/-/libnpmexec-2.0.0.tgz" - integrity sha512-9zHswx//Lp2ao+huWF2aL+6v4haMncyxNusk6Us2fbLNnPh3+rgSkv38LJ2v8gmKS2kAnkUmQf8pHjcZ+7Z3NA== - dependencies: - "@npmcli/arborist" "^2.3.0" - "@npmcli/ci-detect" "^1.3.0" - "@npmcli/run-script" "^1.8.4" - chalk "^4.1.0" - mkdirp-infer-owner "^2.0.0" - npm-package-arg "^8.1.2" - pacote "^11.3.1" - proc-log "^1.0.0" - read "^1.0.7" - read-package-json-fast "^2.0.2" - walk-up-path "^1.0.0" - -libnpmfund@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/libnpmfund/-/libnpmfund-1.1.0.tgz" - integrity sha512-Kfmh3pLS5/RGKG5WXEig8mjahPVOxkik6lsbH4iX0si1xxNi6eeUh/+nF1MD+2cgalsQif3O5qyr6mNz2ryJrQ== - dependencies: - "@npmcli/arborist" "^2.5.0" - -libnpmhook@^6.0.2: - version "6.0.3" - resolved "https://registry.npmjs.org/libnpmhook/-/libnpmhook-6.0.3.tgz" - integrity sha512-3fmkZJibIybzmAvxJ65PeV3NzRc0m4xmYt6scui5msocThbEp4sKFT80FhgrCERYDjlUuFahU6zFNbJDHbQ++g== - dependencies: - aproba "^2.0.0" - npm-registry-fetch "^11.0.0" - -libnpmorg@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/libnpmorg/-/libnpmorg-2.0.3.tgz" - integrity sha512-JSGl3HFeiRFUZOUlGdiNcUZOsUqkSYrg6KMzvPZ1WVZ478i47OnKSS0vkPmX45Pai5mTKuwIqBMcGWG7O8HfdA== - dependencies: - aproba "^2.0.0" - npm-registry-fetch "^11.0.0" - -libnpmpack@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/libnpmpack/-/libnpmpack-2.0.1.tgz" - integrity sha512-He4/jxOwlaQ7YG7sIC1+yNeXeUDQt8RLBvpI68R3RzPMZPa4/VpxhlDo8GtBOBDYoU8eq6v1wKL38sq58u4ibQ== - dependencies: - "@npmcli/run-script" "^1.8.3" - npm-package-arg "^8.1.0" - pacote "^11.2.6" - -libnpmpublish@^4.0.0, libnpmpublish@^4.0.1: +libnpmpublish@^4.0.0: version "4.0.2" resolved "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-4.0.2.tgz" integrity sha512-+AD7A2zbVeGRCFI2aO//oUmapCwy7GHqPXFJh3qpToSRNU+tXKJ2YFUgjt04LPPAf2dlEH95s6EhIHM1J7bmOw== @@ -12986,32 +12760,6 @@ libnpmpublish@^4.0.0, libnpmpublish@^4.0.1: semver "^7.1.3" ssri "^8.0.1" -libnpmsearch@^3.1.1: - version "3.1.2" - resolved "https://registry.npmjs.org/libnpmsearch/-/libnpmsearch-3.1.2.tgz" - integrity sha512-BaQHBjMNnsPYk3Bl6AiOeVuFgp72jviShNBw5aHaHNKWqZxNi38iVNoXbo6bG/Ccc/m1To8s0GtMdtn6xZ1HAw== - dependencies: - npm-registry-fetch "^11.0.0" - -libnpmteam@^2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/libnpmteam/-/libnpmteam-2.0.4.tgz" - integrity sha512-FPrVJWv820FZFXaflAEVTLRWZrerCvfe7ZHSMzJ/62EBlho2KFlYKjyNEsPW3JiV7TLSXi3vo8u0gMwIkXSMTw== - dependencies: - aproba "^2.0.0" - npm-registry-fetch "^11.0.0" - -libnpmversion@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/libnpmversion/-/libnpmversion-1.2.1.tgz" - integrity sha512-AA7x5CFgBFN+L4/JWobnY5t4OAHjQuPbAwUYJ7/NtHuyLut5meb+ne/aj0n7PWNiTGCJcRw/W6Zd2LoLT7EZuQ== - dependencies: - "@npmcli/git" "^2.0.7" - "@npmcli/run-script" "^1.8.4" - json-parse-even-better-errors "^2.3.1" - semver "^7.3.5" - stringify-package "^1.0.1" - libtap@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/libtap/-/libtap-1.1.1.tgz" @@ -13091,6 +12839,15 @@ listr2@1.3.8: through "^2.3.8" uuid "^7.0.2" +lmify@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/lmify/-/lmify-0.3.0.tgz#42a14f6258b97f51cd31b35f7f1a663212fe2da0" + integrity sha512-Yc4LT2QdkZJXTgwrTEV6T3RRpNIVIh0lMEuITUfj8e7SeWO8hq6Llyq7n588LUuX+rkoBnl2AyyrdYYJ4uxODA== + dependencies: + execa "^4.0.0" + fs-extra "^9.0.0" + std-env "^2.2.1" + load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz" @@ -13488,7 +13245,7 @@ make-fetch-happen@^8.0.9: socks-proxy-agent "^5.0.0" ssri "^8.0.0" -make-fetch-happen@^9.0.1, make-fetch-happen@^9.0.3: +make-fetch-happen@^9.0.1: version "9.0.4" resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.0.4.tgz" integrity sha512-sQWNKMYqSmbAGXqJg2jZ+PmHh5JAybvwu0xM8mZR/bsTjGiTASj3ldXJV7KFHy1k/IJIBkjxQFoWIVsv9+PQMg== @@ -14460,7 +14217,7 @@ node-gyp@^5.0.2: tar "^4.4.12" which "^1.3.1" -node-gyp@^7.1.0, node-gyp@^7.1.2: +node-gyp@^7.1.0: version "7.1.2" resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz" integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ== @@ -14645,13 +14402,6 @@ normalize-url@^6.0.1, normalize-url@^6.1.0: resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -npm-audit-report@^2.1.5: - version "2.1.5" - resolved "https://registry.npmjs.org/npm-audit-report/-/npm-audit-report-2.1.5.tgz" - integrity sha512-YB8qOoEmBhUH1UJgh1xFAv7Jg1d+xoNhsDYiFQlEFThEBui0W1vIz2ZK6FVg4WZjwEdl7uBQlm1jy3MUfyHeEw== - dependencies: - chalk "^4.0.0" - npm-bundled@^1.1.1: version "1.1.2" resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz" @@ -14693,7 +14443,7 @@ npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== -npm-package-arg@8.1.5, npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0, npm-package-arg@^8.1.1, npm-package-arg@^8.1.2, npm-package-arg@^8.1.5: +npm-package-arg@8.1.5, npm-package-arg@^8.0.0, npm-package-arg@^8.0.1, npm-package-arg@^8.1.0, npm-package-arg@^8.1.2: version "8.1.5" resolved "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz" integrity sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q== @@ -14712,7 +14462,7 @@ npm-packlist@^2.1.4: npm-bundled "^1.1.1" npm-normalize-package-bin "^1.0.1" -npm-pick-manifest@6.1.1, npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.0, npm-pick-manifest@^6.1.1: +npm-pick-manifest@6.1.1, npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.1: version "6.1.1" resolved "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz" integrity sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA== @@ -14722,13 +14472,6 @@ npm-pick-manifest@6.1.1, npm-pick-manifest@^6.0.0, npm-pick-manifest@^6.1.0, npm npm-package-arg "^8.1.2" semver "^7.3.4" -npm-profile@^5.0.3: - version "5.0.4" - resolved "https://registry.npmjs.org/npm-profile/-/npm-profile-5.0.4.tgz" - integrity sha512-OKtU7yoAEBOnc8zJ+/uo5E4ugPp09sopo+6y1njPp+W99P8DvQon3BJYmpvyK2Bf1+3YV5LN1bvgXRoZ1LUJBA== - dependencies: - npm-registry-fetch "^11.0.0" - npm-registry-fetch@^11.0.0: version "11.0.0" resolved "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz" @@ -14784,11 +14527,6 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npm-user-validate@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/npm-user-validate/-/npm-user-validate-1.0.1.tgz" - integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw== - npm-watch@0.7.0: version "0.7.0" resolved "https://registry.npmjs.org/npm-watch/-/npm-watch-0.7.0.tgz" @@ -14797,81 +14535,7 @@ npm-watch@0.7.0: nodemon "^2.0.3" through2 "^2.0.0" -npm@7.19.1: - version "7.19.1" - resolved "https://registry.npmjs.org/npm/-/npm-7.19.1.tgz" - integrity sha512-aN3hZzGkPzKOyhjXtOhnQTGumorFhgpOU6xfuQsF1nJKh4DhsgfOMG4s/SNx56r4xHPvM5m/sk914wzDgKba3A== - dependencies: - "@npmcli/arborist" "^2.6.4" - "@npmcli/ci-detect" "^1.2.0" - "@npmcli/config" "^2.2.0" - "@npmcli/package-json" "^1.0.1" - "@npmcli/run-script" "^1.8.5" - abbrev "~1.1.1" - ansicolors "~0.3.2" - ansistyles "~0.1.3" - archy "~1.0.0" - byte-size "^7.0.1" - cacache "^15.2.0" - chalk "^4.1.0" - chownr "^2.0.0" - cli-columns "^3.1.2" - cli-table3 "^0.6.0" - columnify "~1.5.4" - glob "^7.1.7" - graceful-fs "^4.2.6" - hosted-git-info "^4.0.2" - ini "^2.0.0" - init-package-json "^2.0.3" - is-cidr "^4.0.2" - json-parse-even-better-errors "^2.3.1" - leven "^3.1.0" - libnpmaccess "^4.0.2" - libnpmdiff "^2.0.4" - libnpmexec "^2.0.0" - libnpmfund "^1.1.0" - libnpmhook "^6.0.2" - libnpmorg "^2.0.2" - libnpmpack "^2.0.1" - libnpmpublish "^4.0.1" - libnpmsearch "^3.1.1" - libnpmteam "^2.0.3" - libnpmversion "^1.2.1" - make-fetch-happen "^9.0.3" - minipass "^3.1.3" - minipass-pipeline "^1.2.4" - mkdirp "^1.0.4" - mkdirp-infer-owner "^2.0.0" - ms "^2.1.2" - node-gyp "^7.1.2" - nopt "^5.0.0" - npm-audit-report "^2.1.5" - npm-package-arg "^8.1.5" - npm-pick-manifest "^6.1.1" - npm-profile "^5.0.3" - npm-registry-fetch "^11.0.0" - npm-user-validate "^1.0.1" - npmlog "~4.1.2" - opener "^1.5.2" - pacote "^11.3.3" - parse-conflict-json "^1.1.1" - qrcode-terminal "^0.12.0" - read "~1.0.7" - read-package-json "^3.0.1" - read-package-json-fast "^2.0.2" - readdir-scoped-modules "^1.1.0" - rimraf "^3.0.2" - semver "^7.3.5" - ssri "^8.0.1" - tar "^6.1.0" - text-table "~0.2.0" - tiny-relative-date "^1.3.0" - treeverse "^1.0.4" - validate-npm-package-name "~3.0.0" - which "^2.0.2" - write-file-atomic "^3.0.3" - -npmlog@^4.0.1, npmlog@^4.1.2, npmlog@~4.1.2: +npmlog@^4.0.1, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -15486,7 +15150,7 @@ pacote@11.3.4: ssri "^8.0.1" tar "^6.1.0" -pacote@^11.1.11, pacote@^11.2.6, pacote@^11.3.0, pacote@^11.3.1, pacote@^11.3.3: +pacote@^11.2.6: version "11.3.5" resolved "https://registry.npmjs.org/pacote/-/pacote-11.3.5.tgz" integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg== @@ -15557,15 +15221,6 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-conflict-json@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-1.1.1.tgz" - integrity sha512-4gySviBiW5TRl7XHvp1agcS7SOe0KZOjC//71dzZVWJrY9hCrgtvl5v3SyIxCZ4fZF47TxD9nfzmxcx76xmbUw== - dependencies: - json-parse-even-better-errors "^2.3.0" - just-diff "^3.0.1" - just-diff-apply "^3.0.0" - parse-duration@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/parse-duration/-/parse-duration-1.0.0.tgz" @@ -16494,11 +16149,6 @@ pretty-bytes@^5.3.0: resolved "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== -proc-log@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/proc-log/-/proc-log-1.0.0.tgz" - integrity sha512-aCk8AO51s+4JyuYGg3Q/a6gnrlDO09NpVWePtjp7xwphcoQ04x5WAfCyugcsbLooWcMJ87CLkD4+604IckEdhg== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" @@ -16535,16 +16185,6 @@ prom-client@13.1.0: dependencies: tdigest "^0.1.1" -promise-all-reject-late@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz" - integrity sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw== - -promise-call-limit@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz" - integrity sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q== - promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" @@ -16736,11 +16376,6 @@ qjobs@^1.2.0: resolved "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz" integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== -qrcode-terminal@^0.12.0: - version "0.12.0" - resolved "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz" - integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== - qs@6.7.0: version "6.7.0" resolved "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz" @@ -16908,7 +16543,7 @@ read-cmd-shim@^2.0.0: resolved "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz" integrity sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw== -read-package-json-fast@^2.0.1, read-package-json-fast@^2.0.2: +read-package-json-fast@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.2.tgz" integrity sha512-5fyFUyO9B799foVk4n6ylcoAktG/FbE3jwRKxvwaeSrIunaoMc0u81dzXxjeAFKOce7O5KncdfwpGvvs6r5PsQ== @@ -16981,7 +16616,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -read@1, read@^1.0.7, read@~1.0.1, read@~1.0.7: +read@1, read@~1.0.1: version "1.0.7" resolved "https://registry.npmjs.org/read/-/read-1.0.7.tgz" integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= @@ -17030,7 +16665,7 @@ readable-stream@~1.0.15: isarray "0.0.1" string_decoder "~0.10.x" -readdir-scoped-modules@^1.0.0, readdir-scoped-modules@^1.1.0: +readdir-scoped-modules@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz" integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== @@ -18595,6 +18230,13 @@ statsd-parser@~0.0.4: resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +std-env@^2.2.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-2.3.0.tgz#66d4a4a4d5224242ed8e43f5d65cfa9095216eee" + integrity sha512-4qT5B45+Kjef2Z6pE0BkskzsH0GO7GrND0wGlTM1ioUe3v0dGYx9ZJH0Aro/YyA8fqQ5EyIKDRjZojJYMFTflw== + dependencies: + ci-info "^3.0.0" + stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz" @@ -18784,11 +18426,6 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -stringify-package@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz" - integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg== - strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" @@ -19267,7 +18904,7 @@ temp@0.9.1: temp@0.9.4: version "0.9.4" - resolved "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.4.tgz#cd20a8580cb63635d0e4e9d4bd989d44286e7620" integrity sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA== dependencies: mkdirp "^0.5.1" @@ -19341,7 +18978,7 @@ text-extensions@^1.0.0: resolved "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -text-table@0.2.0, text-table@^0.2.0, text-table@~0.2.0: +text-table@0.2.0, text-table@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= @@ -19396,11 +19033,6 @@ timsort@^0.3.0: resolved "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -tiny-relative-date@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz" - integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== - tmp@0.0.28: version "0.0.28" resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz" @@ -19542,11 +19174,6 @@ tree-kill@1.2.2, tree-kill@^1.2.2: resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== -treeverse@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/treeverse/-/treeverse-1.0.4.tgz" - integrity sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g== - treport@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/treport/-/treport-2.0.2.tgz" @@ -20261,7 +19888,7 @@ validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: +validate-npm-package-name@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz" integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= @@ -20317,11 +19944,6 @@ vscode-uri@^3.0.2: resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.2.tgz" integrity sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA== -walk-up-path@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz" - integrity sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg== - watchpack@^2.0.0, watchpack@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz"