From d0df63395f0cede5b4050dfef5e4b5f705a771b0 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Wed, 26 Apr 2023 17:35:34 +0100 Subject: [PATCH 001/321] perf!: rearchitect plugin loader to lazily load plugins currently only converted the plugins next-static uses to facilitate testing --- core/cli/src/config.ts | 21 +--- core/cli/src/help.ts | 8 +- core/cli/src/index.ts | 13 +- core/cli/src/install.ts | 10 +- core/cli/src/messages.ts | 28 ++--- core/cli/src/plugin.ts | 139 +++------------------ core/cli/src/rc-file.ts | 4 +- core/create/src/index.ts | 2 + lib/types/src/index.ts | 29 ++--- package-lock.json | 110 ++++++++-------- plugins/circleci-deploy/.toolkitrc.yml | 8 ++ plugins/circleci/.toolkitrc.yml | 3 + plugins/eslint/.toolkitrc.yml | 3 + plugins/eslint/src/index.ts | 2 +- plugins/heroku/.toolkitrc.yml | 11 ++ plugins/heroku/src/index.ts | 2 +- plugins/husky-npm/.toolkitrc.yml | 3 + plugins/lint-staged-npm/.toolkitrc.yml | 4 + plugins/lint-staged/.toolkitrc.yml | 3 + plugins/lint-staged/src/index.ts | 2 +- plugins/mocha/.toolkitrc.yml | 3 + plugins/mocha/src/index.ts | 2 +- plugins/n-test/.toolkitrc.yml | 3 + plugins/n-test/src/index.ts | 2 +- plugins/next-router/.toolkitrc.yml | 3 + plugins/next-router/src/index.ts | 2 +- plugins/node/.toolkitrc.yml | 3 + plugins/node/src/index.ts | 2 +- plugins/nodemon/.toolkitrc.yml | 3 + plugins/nodemon/src/index.ts | 2 +- plugins/npm/.toolkitrc.yml | 8 ++ plugins/npm/src/index.ts | 4 +- plugins/upload-assets-to-s3/.toolkitrc.yml | 3 + plugins/upload-assets-to-s3/src/index.ts | 2 +- plugins/webpack/.toolkitrc.yml | 5 + plugins/webpack/src/index.ts | 2 +- 36 files changed, 201 insertions(+), 253 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index d3d284f15..a5e1ddfff 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -30,10 +30,10 @@ export interface RawConfig { root: string plugins: { [id: string]: Validated } resolvedPlugins: Set - tasks: { [id: string]: TaskClass | Conflict } + tasks: { [id: string]: string | Conflict } hookTasks: { [id: string]: HookTask | Conflict } options: { [id: string]: PluginOptions | Conflict | undefined } - hooks: { [id: string]: Hook | Conflict> } + hooks: { [id: string]: string | Conflict } } export type ValidPluginsConfig = Omit & { @@ -49,10 +49,10 @@ export type ValidOptions = { } export type ValidConfig = Omit & { - tasks: { [id: string]: TaskClass } + tasks: { [id: string]: string } hookTasks: { [id: string]: HookTask } options: ValidOptions - hooks: { [id: string]: Hook } + hooks: { [id: string]: string } } const coreRoot = path.resolve(__dirname, '../') @@ -212,19 +212,6 @@ export function validatePlugins(config: RawConfig): Validated ({ ...config, plugins: Object.fromEntries(plugins) })) } -export async function checkInstall(config: ValidConfig): Promise { - const definedHooks = withoutConflicts(Object.values(config.hooks)) - const uninstalledHooks = await asyncFilter(definedHooks, async (hook) => { - return !(await hook.check()) - }) - - if (uninstalledHooks.length > 0) { - const error = new ToolKitError('There are problems with your Tool Kit installation.') - error.details = formatUninstalledHooks(uninstalledHooks) - throw error - } -} - export function loadConfig(logger: Logger, options?: { validate?: true }): Promise export function loadConfig(logger: Logger, options?: { validate?: false }): Promise diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index da0a8424f..5eb563e45 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -1,4 +1,4 @@ -import { checkInstall, loadConfig } from './config' +import { loadConfig } from './config' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' @@ -16,8 +16,6 @@ export default async function showHelp(logger: Logger, hooks: string[]): Promise } } - await checkInstall(config) - const missingHooks = hooks.filter((hook) => !config.hooks[hook]) logger.info(` @@ -52,9 +50,7 @@ ${(Hook.constructor as any).description ? (Hook.constructor as any).description ${ tasks && tasks.tasks.length ? `runs ${tasks.tasks.length > 1 ? 'these tasks' : 'this task'}: -${tasks.tasks - .map((task) => `- ${styles.task(task)} ${styles.dim(config.tasks[task].description)}`) - .join('\n')}` +${tasks.tasks.map((task) => `- ${styles.task(task)}`).join('\n')}` : styles.dim('no tasks configured to run on this hook.') } ${styles.ruler()} diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 304a2e03e..4ca648dbb 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -1,9 +1,10 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -import { checkInstall, loadConfig } from './config' +import { loadConfig } from './config' import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' import { formatPluginTree } from './messages' +import { TaskClass } from '@dotcom-tool-kit/types' type ErrorSummary = { hook: string @@ -52,8 +53,6 @@ ${availableHooks}` } } - await checkInstall(config) - if (shouldDisableNativeFetch()) { process.execArgv.push('--no-experimental-fetch') } @@ -68,14 +67,16 @@ ${availableHooks}` const assignment = config.hookTasks[hook] for (const id of assignment.tasks) { - const Task = config.tasks[id] - const options = Task.plugin ? getOptions(Task.plugin.id as OptionKey) : {} + const pluginId = config.tasks[id] + const Task = (await import(pluginId)).tasks[id] as TaskClass + + const options = getOptions(pluginId as OptionKey) /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- * `Task` is an abstract class. Here we know it's a concrete subclass * but typescript doesn't, so cast it to any. **/ - const task = new (Task as any)(logger, options) + const task = new (Task as any)(logger, id, options) logger.info(styles.taskHeader(`running ${styles.task(id)} task`)) try { diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 555c86085..a59359922 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -1,5 +1,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' +import { Hook, HookConstructor } from '@dotcom-tool-kit/types' import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' import { loadConfig, ValidConfig } from './config' @@ -27,7 +28,14 @@ export default async function installHooks(logger: Logger): Promise const errors: Error[] = [] // group hooks without an installGroup separately so that their check() // method runs independently - const groups = groupBy(config.hooks, (hook) => hook.installGroup ?? '__' + hook.id) + const hooks: Hook[] = await Promise.all( + Object.entries(config.hooks).map(async ([hookName, pluginId]) => { + const plugin = await import(pluginId) + const Hook = plugin.hooks[hookName] as HookConstructor + return new Hook(logger, hookName) + }) + ) + const groups = groupBy(hooks, (hook) => hook.installGroup ?? '__' + hook.id) for (const group of Object.values(groups)) { try { const allChecksPassed = await asyncEvery(group, (hook) => hook.check()) diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index f334d4b65..b520cafb6 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -1,33 +1,29 @@ -import type { PluginOptions } from './config' -import type { Conflict } from './conflict' -import type { HookTask } from './hook' import { styles as s, styles } from '@dotcom-tool-kit/logger' -import type { Plugin, Hook, TaskClass } from '@dotcom-tool-kit/types' +import type { Hook, Plugin } from '@dotcom-tool-kit/types' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' +import type { PluginOptions } from './config' +import type { Conflict } from './conflict' +import type { HookTask } from './hook' -const formatTaskConflict = (conflict: Conflict): string => - `- ${s.task(conflict.conflicting[0].id || 'unknown task')} ${s.dim( +const formatTaskConflict = (conflict: Conflict): string => + `- ${s.task(conflict.conflicting[0] ?? 'unknown task')} ${s.dim( 'from plugins' - )} ${conflict.conflicting - .map((task) => s.plugin(task.plugin ? task.plugin.id : 'unknown plugin')) - .join(s.dim(', '))}` + )} ${conflict.conflicting.map((task) => s.plugin(task ?? 'unknown plugin')).join(s.dim(', '))}` -export const formatTaskConflicts = (conflicts: Conflict[]): string => `${s.heading( +export const formatTaskConflicts = (conflicts: Conflict[]): string => `${s.heading( 'There are multiple plugins that include the same tasks' )}: ${conflicts.map(formatTaskConflict).join('\n')} You must resolve this conflict by removing all but one of these plugins.` -const formatHookConflict = (conflict: Conflict>): string => - `- ${s.hook(conflict.conflicting[0].id || 'unknown event')} ${s.dim( +const formatHookConflict = (conflict: Conflict): string => + `- ${s.hook(conflict.conflicting[0] ?? 'unknown event')} ${s.dim( 'from plugins' - )} ${conflict.conflicting - .map((task) => s.plugin(task.plugin ? task.plugin.id : 'unknown plugin')) - .join(s.dim(', '))}` + )} ${conflict.conflicting.map((task) => s.plugin(task ?? 'unknown plugin')).join(s.dim(', '))}` -export const formatHookConflicts = (conflicts: Conflict>[]): string => `${s.heading( +export const formatHookConflicts = (conflicts: Conflict[]): string => `${s.heading( 'There are multiple plugins that include the same hooks' )}: ${conflicts.map(formatHookConflict).join('\n')} diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index b7829f51b..ca77997a5 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,17 +1,12 @@ import { styles as s } from '@dotcom-tool-kit/logger' import { - Hook, - joinValidated, mapValidated, mapValidationError, Plugin, - PluginModule, reduceValidated, - Task, Valid, Validated } from '@dotcom-tool-kit/types' -import isPlainObject from 'lodash/isPlainObject' import resolveFrom from 'resolve-from' import type { Logger } from 'winston' import { PluginOptions, RawConfig, ValidPluginsConfig } from './config' @@ -19,8 +14,6 @@ import { Conflict, isConflict } from './conflict' import type { HookTask } from './hook' import { loadToolKitRC } from './rc-file' -type RawPluginModule = Partial - function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { if (!possibleDescendent.parent) { return false @@ -33,74 +26,6 @@ function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boo const indentReasons = (reasons: string): string => reasons.replace(/\n/g, '\n ') -export function validatePlugin(plugin: unknown): Validated { - const errors: string[] = [] - const rawPlugin = plugin as RawPluginModule - - if (rawPlugin.tasks) { - if (!Array.isArray(rawPlugin.tasks)) { - errors.push(`the exported ${s.code('tasks')} value from this plugin is not an array`) - } else { - const validatedTasks = reduceValidated( - rawPlugin.tasks.map((task) => - mapValidationError(Task.isCompatible(task), (reasons) => [ - `the task ${s.task(task.name)} is not a compatible instance of ${s.code( - 'Task' - )}:\n - ${reasons.join('\n - ')}` - ]) - ) - ) - if (!validatedTasks.valid) { - errors.push(...validatedTasks.reasons) - } - } - } - - if (rawPlugin.hooks) { - if (!isPlainObject(rawPlugin.hooks)) { - errors.push(`the exported ${s.code('hooks')} value from this plugin is not an object`) - } else { - const validatedHooks = reduceValidated( - Object.entries(rawPlugin.hooks).map(([id, hook]) => - mapValidationError(Hook.isCompatible(hook), (reasons) => [ - `the hook ${s.hook(id)} is not a compatible instance of ${s.code('Hook')}:\n - ${reasons.join( - '\n - ' - )}` - ]) - ) - ) - if (!validatedHooks.valid) { - errors.push(...validatedHooks.reasons) - } - } - } - - if (errors.length > 0) { - return { valid: false, reasons: errors } - } else { - const pluginModule = { tasks: rawPlugin.tasks ?? [], hooks: rawPlugin.hooks ?? {} } - return { valid: true, value: pluginModule } - } -} - -async function importPlugin(pluginPath: string): Promise> { - try { - // pluginPath is an absolute resolved path to a plugin module as found from its parent - const pluginModule = (await import(pluginPath)) as unknown - return validatePlugin(pluginModule) - } catch (e) { - const err = e as Error - return { - valid: false, - reasons: [ - `an error was thrown when loading this plugin's entrypoint:\n ${s.code( - indentReasons(err.toString()) - )}` - ] - } - } -} - export async function loadPlugin( id: string, config: RawConfig, @@ -134,37 +59,19 @@ export async function loadPlugin( config.plugins[id] = plugin - // start loading rc file in the background - const rcFilePromise = loadToolKitRC(logger, pluginRoot, isAppRoot) - - // start loading module in the background - const pluginModulePromise: Promise> = isAppRoot - ? Promise.resolve({ valid: true, value: undefined }) - : importPlugin(pluginRoot) - - // ESlint disable explanation: erroring due to a possible race condition but is a false positive since the plugin variable isn't from another scope and can't be written to concurrently. - // eslint-disable-next-line require-atomic-updates - plugin.value.rcFile = await rcFilePromise + plugin.value.rcFile = await loadToolKitRC(logger, pluginRoot, isAppRoot) - // start loading child plugins in the background - const childrenPromise = Promise.all( + const children = await Promise.all( plugin.value.rcFile.plugins.map((child) => loadPlugin(child, config, logger, plugin.value)) ) - // wait for pending promises concurrently - const [module, children] = await Promise.all([pluginModulePromise, childrenPromise]) - - const validatedModule = mapValidationError(module, (reasons) => [ - indentReasons(`plugin ${s.plugin(id)} failed to load because:\n- ${reasons.join('\n- ')}`) - ]) const validatedChildren = mapValidationError(reduceValidated(children), (reasons) => [ indentReasons(`some child plugins of ${s.plugin(id)} failed to load:\n- ${reasons.join('\n- ')}`) ]) - return mapValidated(joinValidated(validatedModule, validatedChildren), ([module, children]) => { + return mapValidated(validatedChildren, (children) => { // avoid cloning the plugin value with an object spread as we do object // reference comparisons in multiple places - plugin.value.module = module plugin.value.children = children return plugin.value }) @@ -184,50 +91,40 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger } } - if (plugin.module) { + if (plugin.rcFile) { // add plugin tasks to our task registry, handling any conflicts - for (const newTask of plugin.module.tasks || []) { - const taskId = newTask.name - const existingTask = config.tasks[taskId] - - newTask.plugin = plugin - newTask.id = taskId + for (const taskName of plugin.rcFile.tasks || []) { + const existingTaskId = config.tasks[taskName] - if (existingTask) { - const conflicting = isConflict(existingTask) ? existingTask.conflicting : [existingTask] + if (existingTaskId) { + const conflicting = isConflict(existingTaskId) ? existingTaskId.conflicting : [existingTaskId] - config.tasks[taskId] = { + config.tasks[taskName] = { plugin, - conflicting: conflicting.concat(newTask) + conflicting: conflicting.concat(plugin.id) } } else { - config.tasks[taskId] = newTask + config.tasks[taskName] = plugin.id } } // add hooks to the registry, handling any conflicts // TODO refactor with command conflict handler - for (const [hookId, hookClass] of Object.entries(plugin.module.hooks || [])) { - const existingHook = config.hooks[hookId] - const newHook = new hookClass(logger) + for (const hookName of plugin.rcFile.installs || []) { + const existingHookId = config.hooks[hookName] - newHook.id = hookId - newHook.plugin = plugin + if (existingHookId) { + const conflicting = isConflict(existingHookId) ? existingHookId.conflicting : [existingHookId] - if (existingHook) { - const conflicting = isConflict(existingHook) ? existingHook.conflicting : [existingHook] - - config.hooks[hookId] = { + config.hooks[hookName] = { plugin, - conflicting: conflicting.concat(newHook) + conflicting: conflicting.concat(plugin.id) } } else { - config.hooks[hookId] = newHook + config.hooks[hookName] = plugin.id } } - } - if (plugin.rcFile) { // load plugin hook tasks. do this after loading child plugins, so // parent hooks get assigned after child hooks and can override them for (const [id, configHookTask] of Object.entries(plugin.rcFile.hooks)) { diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 6294b85c1..cd531cbba 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -5,7 +5,7 @@ import * as path from 'path' import type { Logger } from 'winston' export const explorer = cosmiconfig('toolkit', { ignoreEmptySearchPlaces: false }) -const emptyConfig = { plugins: [], hooks: {}, options: {} } +const emptyConfig = { plugins: [], installs: [], tasks: [], hooks: {}, options: {} } let rootConfig: string | undefined type RawRCFile = { @@ -35,6 +35,8 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo const config: RawRCFile = result.config return { plugins: config.plugins ?? [], + installs: config.installs ?? [], + tasks: config.tasks ?? [], hooks: config.hooks ?? {}, options: config.options ?? {} } diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 17192fd78..2e44910c5 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -113,6 +113,8 @@ async function executeMigration( async function main() { const toolKitConfig: RCFile = { plugins: [], + installs: [], + tasks: [], hooks: {}, options: {} } diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 00f09908d..633ab1309 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -137,8 +137,7 @@ abstract class Base { export abstract class Task extends Base { static description: string - static plugin?: Plugin - static id?: string + id: string static get [typeSymbol](): symbol { return taskSymbol @@ -151,26 +150,25 @@ export abstract class Task extends Base { options: z.output logger: Logger - constructor(logger: Logger, options: z.output) { + constructor(logger: Logger, id: string, options: z.output) { super() - const staticThis = this.constructor as typeof Task + this.id = id this.options = options - this.logger = logger.child({ task: staticThis.id }) + this.logger = logger.child({ task: id }) } abstract run(files?: string[]): Promise } export type TaskClass = { - new (logger: Logger, options: Partial>): Task + new (logger: Logger, id: string, options: Partial>): Task } & typeof Task export abstract class Hook extends Base { - id?: string - plugin?: Plugin logger: Logger static description?: string + id: string // This field is used to collect hooks that share state when running their // install methods. All hooks in the same group will run their install method // one after the other, and then their commitInstall method will be run with @@ -185,9 +183,10 @@ export abstract class Hook extends Base { return hookSymbol } - constructor(logger: Logger) { + constructor(logger: Logger, id: string) { super() + this.id = id this.logger = logger.child({ hook: this.constructor.name }) } @@ -200,10 +199,12 @@ export abstract class Hook extends Base { } } -export type HookConstructor = { new (logger: Logger): Hook } +export type HookConstructor = { new (logger: Logger, id: string): Hook } export type RCFile = { plugins: string[] + installs: string[] + tasks: string[] hooks: { [id: string]: string | string[] } options: { [id: string]: Record } } @@ -212,14 +213,6 @@ export interface Plugin { id: string root: string rcFile?: RCFile - module?: PluginModule parent?: Plugin children?: Plugin[] } - -export interface PluginModule { - tasks: TaskClass[] - hooks: { - [id: string]: HookConstructor - } -} diff --git a/package-lock.json b/package-lock.json index 3e6478616..1dd4ac94c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,7 @@ }, "core/cli": { "name": "dotcom-tool-kit", - "version": "3.4.0", + "version": "3.4.5", "license": "MIT", "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", @@ -68,15 +68,15 @@ }, "devDependencies": { "@dotcom-tool-kit/babel": "^3.2.0", - "@dotcom-tool-kit/backend-heroku-app": "^3.1.0", - "@dotcom-tool-kit/circleci": "^5.4.0", - "@dotcom-tool-kit/circleci-deploy": "^3.3.0", + "@dotcom-tool-kit/backend-heroku-app": "^3.1.4", + "@dotcom-tool-kit/circleci": "^6.0.1", + "@dotcom-tool-kit/circleci-deploy": "^3.4.3", "@dotcom-tool-kit/eslint": "^3.2.0", - "@dotcom-tool-kit/frontend-app": "^3.2.0", - "@dotcom-tool-kit/heroku": "^3.4.0", + "@dotcom-tool-kit/frontend-app": "^3.2.4", + "@dotcom-tool-kit/heroku": "^3.4.1", "@dotcom-tool-kit/mocha": "^3.2.0", - "@dotcom-tool-kit/n-test": "^3.3.0", - "@dotcom-tool-kit/npm": "^3.3.0", + "@dotcom-tool-kit/n-test": "^3.3.1", + "@dotcom-tool-kit/npm": "^3.3.1", "@dotcom-tool-kit/webpack": "^3.2.0", "@jest/globals": "^27.4.6", "@types/lodash": "^4.14.185", @@ -122,7 +122,7 @@ }, "core/create": { "name": "@dotcom-tool-kit/create", - "version": "3.5.2", + "version": "3.7.1", "license": "ISC", "dependencies": { "@aws-sdk/client-iam": "^3.282.0", @@ -157,7 +157,7 @@ "@types/pacote": "^11.1.3", "@types/prompts": "^2.0.14", "cosmiconfig": "^7.0.1", - "dotcom-tool-kit": "^3.4.0", + "dotcom-tool-kit": "^3.4.5", "type-fest": "^3.13.1" }, "engines": { @@ -1212,7 +1212,7 @@ }, "lib/state": { "name": "@dotcom-tool-kit/state", - "version": "3.2.0", + "version": "3.3.0", "license": "ISC", "dependencies": { "tslib": "^2.3.1" @@ -28855,10 +28855,10 @@ }, "plugins/backend-app": { "name": "@dotcom-tool-kit/backend-app", - "version": "3.2.0", + "version": "3.2.4", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/backend-heroku-app": "^3.1.0" + "@dotcom-tool-kit/backend-heroku-app": "^3.1.4" }, "engines": { "node": "16.x || 18.x || 20.x", @@ -28870,13 +28870,13 @@ }, "plugins/backend-heroku-app": { "name": "@dotcom-tool-kit/backend-heroku-app", - "version": "3.1.0", + "version": "3.1.4", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/circleci-deploy": "^3.3.0", - "@dotcom-tool-kit/heroku": "^3.4.0", - "@dotcom-tool-kit/node": "^3.4.0", - "@dotcom-tool-kit/npm": "^3.3.0" + "@dotcom-tool-kit/circleci-deploy": "^3.4.3", + "@dotcom-tool-kit/heroku": "^3.4.1", + "@dotcom-tool-kit/node": "^3.4.1", + "@dotcom-tool-kit/npm": "^3.3.1" }, "engines": { "node": "16.x || 18.x || 20.x", @@ -28888,13 +28888,13 @@ }, "plugins/backend-serverless-app": { "name": "@dotcom-tool-kit/backend-serverless-app", - "version": "3.1.0", + "version": "3.2.7", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/circleci-deploy": "^3.3.0", - "@dotcom-tool-kit/node": "^3.4.0", - "@dotcom-tool-kit/npm": "^3.3.0", - "@dotcom-tool-kit/serverless": "^2.3.0" + "@dotcom-tool-kit/circleci-deploy": "^3.4.3", + "@dotcom-tool-kit/node": "^3.4.1", + "@dotcom-tool-kit/npm": "^3.3.1", + "@dotcom-tool-kit/serverless": "^2.4.4" }, "engines": { "node": "16.x || 18.x || 20.x", @@ -28906,12 +28906,12 @@ }, "plugins/circleci": { "name": "@dotcom-tool-kit/circleci", - "version": "5.4.0", + "version": "6.0.1", "license": "ISC", "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0", "jest-diff": "^29.5.0", "lodash": "^4.17.21", @@ -28936,10 +28936,10 @@ }, "plugins/circleci-deploy": { "name": "@dotcom-tool-kit/circleci-deploy", - "version": "3.3.0", + "version": "3.4.3", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/circleci": "^5.4.0", + "@dotcom-tool-kit/circleci": "^6.0.1", "tslib": "^2.3.1" }, "devDependencies": { @@ -28960,11 +28960,11 @@ }, "plugins/circleci-heroku": { "name": "@dotcom-tool-kit/circleci-heroku", - "version": "3.2.0", + "version": "3.2.4", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/circleci-deploy": "^3.3.0", - "@dotcom-tool-kit/heroku": "^3.4.0", + "@dotcom-tool-kit/circleci-deploy": "^3.4.3", + "@dotcom-tool-kit/heroku": "^3.4.1", "tslib": "^2.3.1" }, "engines": { @@ -28982,11 +28982,11 @@ }, "plugins/circleci-npm": { "name": "@dotcom-tool-kit/circleci-npm", - "version": "5.3.0", + "version": "5.3.3", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/circleci": "^5.4.0", - "@dotcom-tool-kit/npm": "^3.3.0", + "@dotcom-tool-kit/circleci": "^6.0.1", + "@dotcom-tool-kit/npm": "^3.3.1", "@dotcom-tool-kit/types": "^3.6.0", "tslib": "^2.3.1" }, @@ -29104,11 +29104,11 @@ }, "plugins/component": { "name": "@dotcom-tool-kit/component", - "version": "4.1.0", + "version": "4.1.3", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/circleci-npm": "^5.3.0", - "@dotcom-tool-kit/npm": "^3.3.0" + "@dotcom-tool-kit/circleci-npm": "^5.3.3", + "@dotcom-tool-kit/npm": "^3.3.1" }, "engines": { "node": "16.x || 18.x || 20.x", @@ -29120,12 +29120,12 @@ }, "plugins/cypress": { "name": "@dotcom-tool-kit/cypress", - "version": "3.4.0", + "version": "4.0.1", "license": "ISC", "dependencies": { "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0" }, "engines": { @@ -29360,10 +29360,10 @@ }, "plugins/frontend-app": { "name": "@dotcom-tool-kit/frontend-app", - "version": "3.2.0", + "version": "3.2.4", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/backend-heroku-app": "^3.1.0", + "@dotcom-tool-kit/backend-heroku-app": "^3.1.4", "@dotcom-tool-kit/upload-assets-to-s3": "^3.2.0", "@dotcom-tool-kit/webpack": "^3.2.0" }, @@ -29377,16 +29377,16 @@ }, "plugins/heroku": { "name": "@dotcom-tool-kit/heroku", - "version": "3.4.0", + "version": "3.4.1", "license": "ISC", "dependencies": { "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/npm": "^3.3.0", + "@dotcom-tool-kit/npm": "^3.3.1", "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "@octokit/request": "^5.6.0", @@ -29593,11 +29593,11 @@ }, "plugins/n-test": { "name": "@dotcom-tool-kit/n-test", - "version": "3.3.0", + "version": "3.3.1", "license": "ISC", "dependencies": { "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0", "@financial-times/n-test": "^6.1.0-beta.1", "tslib": "^2.3.1" @@ -29714,13 +29714,13 @@ }, "plugins/next-router": { "name": "@dotcom-tool-kit/next-router", - "version": "3.4.0", + "version": "3.4.1", "license": "ISC", "dependencies": { "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0", "ft-next-router": "^3.0.0", "tslib": "^2.3.1" @@ -29845,12 +29845,12 @@ }, "plugins/node": { "name": "@dotcom-tool-kit/node", - "version": "3.4.0", + "version": "3.4.1", "license": "ISC", "dependencies": { "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0", "get-port": "^5.1.1", "tslib": "^2.3.1", @@ -29871,12 +29871,12 @@ }, "plugins/nodemon": { "name": "@dotcom-tool-kit/nodemon", - "version": "3.4.0", + "version": "3.4.1", "license": "ISC", "dependencies": { "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0", "get-port": "^5.1.1", "tslib": "^2.3.1" @@ -29900,13 +29900,13 @@ }, "plugins/npm": { "name": "@dotcom-tool-kit/npm", - "version": "3.3.0", + "version": "3.3.1", "license": "ISC", "dependencies": { "@actions/exec": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0", "libnpmpack": "^3.1.0", "libnpmpublish": "^5.0.1", @@ -30163,13 +30163,13 @@ }, "plugins/serverless": { "name": "@dotcom-tool-kit/serverless", - "version": "2.3.0", + "version": "2.4.4", "license": "ISC", "dependencies": { "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/options": "^3.2.0", - "@dotcom-tool-kit/state": "^3.2.0", + "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0", "get-port": "^5.1.1", "tslib": "^2.3.1", diff --git a/plugins/circleci-deploy/.toolkitrc.yml b/plugins/circleci-deploy/.toolkitrc.yml index 067c53577..76ba0bafa 100644 --- a/plugins/circleci-deploy/.toolkitrc.yml +++ b/plugins/circleci-deploy/.toolkitrc.yml @@ -1,2 +1,10 @@ plugins: - '@dotcom-tool-kit/circleci' + +installs: + - 'deploy:review' + - 'deploy:staging' + - 'test:review' + - 'test:staging' + - 'teardown:staging' + - 'deploy:production' diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index e69de29bb..93d8bc9c8 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -0,0 +1,3 @@ +installs: + - 'build:ci' + - 'test:ci' diff --git a/plugins/eslint/.toolkitrc.yml b/plugins/eslint/.toolkitrc.yml index c6a9d9f2a..7c45f86a7 100644 --- a/plugins/eslint/.toolkitrc.yml +++ b/plugins/eslint/.toolkitrc.yml @@ -1,3 +1,6 @@ +tasks: + - Eslint + hooks: 'test:local': Eslint 'test:ci': Eslint diff --git a/plugins/eslint/src/index.ts b/plugins/eslint/src/index.ts index d599ac30e..062f70512 100644 --- a/plugins/eslint/src/index.ts +++ b/plugins/eslint/src/index.ts @@ -1,3 +1,3 @@ import Eslint from './tasks/eslint' -export const tasks = [Eslint] +export const tasks = { Eslint } diff --git a/plugins/heroku/.toolkitrc.yml b/plugins/heroku/.toolkitrc.yml index 6fd954f47..7ed47c0a1 100644 --- a/plugins/heroku/.toolkitrc.yml +++ b/plugins/heroku/.toolkitrc.yml @@ -2,5 +2,16 @@ plugins: - '@dotcom-tool-kit/npm' - '@dotcom-tool-kit/doppler' # required so the create script knows we need its options +installs: + - 'cleanup:remote' + - 'release:remote' + - 'build:remote' + +tasks: + - HerokuProduction + - HerokuStaging + - HerokuReview + - HerokuTeardown + hooks: 'cleanup:remote': NpmPrune diff --git a/plugins/heroku/src/index.ts b/plugins/heroku/src/index.ts index 6cd498d7b..e818a2c0f 100644 --- a/plugins/heroku/src/index.ts +++ b/plugins/heroku/src/index.ts @@ -25,4 +25,4 @@ export const hooks = { 'build:remote': BuildRemote } -export const tasks = [HerokuProduction, HerokuStaging, HerokuReview, HerokuTeardown] +export const tasks = { HerokuProduction, HerokuStaging, HerokuReview, HerokuTeardown } diff --git a/plugins/husky-npm/.toolkitrc.yml b/plugins/husky-npm/.toolkitrc.yml index e69de29bb..cfcdf6196 100644 --- a/plugins/husky-npm/.toolkitrc.yml +++ b/plugins/husky-npm/.toolkitrc.yml @@ -0,0 +1,3 @@ +installs: + - 'git:precommit' + - 'git:commitmsg' diff --git a/plugins/lint-staged-npm/.toolkitrc.yml b/plugins/lint-staged-npm/.toolkitrc.yml index 03647dfa9..29f671413 100644 --- a/plugins/lint-staged-npm/.toolkitrc.yml +++ b/plugins/lint-staged-npm/.toolkitrc.yml @@ -1,3 +1,7 @@ plugins: - '@dotcom-tool-kit/lint-staged' - '@dotcom-tool-kit/husky-npm' + +installs: + - 'test:staged' + - 'format:staged' diff --git a/plugins/lint-staged/.toolkitrc.yml b/plugins/lint-staged/.toolkitrc.yml index 0fd58a55e..58ec908f3 100644 --- a/plugins/lint-staged/.toolkitrc.yml +++ b/plugins/lint-staged/.toolkitrc.yml @@ -1,2 +1,5 @@ +tasks: + - LintStaged + hooks: 'git:precommit': LintStaged diff --git a/plugins/lint-staged/src/index.ts b/plugins/lint-staged/src/index.ts index ffca0f886..68f006aed 100644 --- a/plugins/lint-staged/src/index.ts +++ b/plugins/lint-staged/src/index.ts @@ -1,4 +1,4 @@ import LintStaged from './tasks/lint-staged' -export const tasks = [LintStaged] +export const tasks = { LintStaged } export { LintStagedHook } from './hook' diff --git a/plugins/mocha/.toolkitrc.yml b/plugins/mocha/.toolkitrc.yml index bf812f6d4..7b7c9b9e9 100644 --- a/plugins/mocha/.toolkitrc.yml +++ b/plugins/mocha/.toolkitrc.yml @@ -1,3 +1,6 @@ +tasks: + - Mocha + hooks: 'test:local': Mocha 'test:ci': Mocha diff --git a/plugins/mocha/src/index.ts b/plugins/mocha/src/index.ts index 49e8daba9..4a82c28bd 100644 --- a/plugins/mocha/src/index.ts +++ b/plugins/mocha/src/index.ts @@ -1,3 +1,3 @@ import Mocha from './tasks/mocha' -export const tasks = [Mocha] +export const tasks = { Mocha } diff --git a/plugins/n-test/.toolkitrc.yml b/plugins/n-test/.toolkitrc.yml index bc99b350f..1493160e5 100644 --- a/plugins/n-test/.toolkitrc.yml +++ b/plugins/n-test/.toolkitrc.yml @@ -1,3 +1,6 @@ +tasks: + - NTest + hooks: 'test:review': NTest 'test:staging': NTest diff --git a/plugins/n-test/src/index.ts b/plugins/n-test/src/index.ts index 3eaa19d0d..faefa7cf7 100644 --- a/plugins/n-test/src/index.ts +++ b/plugins/n-test/src/index.ts @@ -1,3 +1,3 @@ import NTest from './tasks/n-test' -export const tasks = [NTest] +export const tasks = { NTest } diff --git a/plugins/next-router/.toolkitrc.yml b/plugins/next-router/.toolkitrc.yml index aa4680411..045d3a139 100644 --- a/plugins/next-router/.toolkitrc.yml +++ b/plugins/next-router/.toolkitrc.yml @@ -1,6 +1,9 @@ plugins: - '@dotcom-tool-kit/doppler' +tasks: + - NextRouter + hooks: run:local: - NextRouter diff --git a/plugins/next-router/src/index.ts b/plugins/next-router/src/index.ts index 6eda59f4b..2c56dc58f 100644 --- a/plugins/next-router/src/index.ts +++ b/plugins/next-router/src/index.ts @@ -1,3 +1,3 @@ import NextRouter from './tasks/next-router' -export const tasks = [NextRouter] +export const tasks = { NextRouter } diff --git a/plugins/node/.toolkitrc.yml b/plugins/node/.toolkitrc.yml index 025a1ef46..48f385d68 100644 --- a/plugins/node/.toolkitrc.yml +++ b/plugins/node/.toolkitrc.yml @@ -1,5 +1,8 @@ plugins: - '@dotcom-tool-kit/doppler' +tasks: + - Node + hooks: 'run:local': Node diff --git a/plugins/node/src/index.ts b/plugins/node/src/index.ts index 2cda603a7..9cbead2f9 100644 --- a/plugins/node/src/index.ts +++ b/plugins/node/src/index.ts @@ -1,3 +1,3 @@ import Node from './tasks/node' -export const tasks = [Node] +export const tasks = { Node } diff --git a/plugins/nodemon/.toolkitrc.yml b/plugins/nodemon/.toolkitrc.yml index 495274862..d59245959 100644 --- a/plugins/nodemon/.toolkitrc.yml +++ b/plugins/nodemon/.toolkitrc.yml @@ -1,5 +1,8 @@ plugins: - '@dotcom-tool-kit/doppler' +tasks: + - Nodemon + hooks: 'run:local': Nodemon diff --git a/plugins/nodemon/src/index.ts b/plugins/nodemon/src/index.ts index 4fefb8d8e..91125b1f2 100644 --- a/plugins/nodemon/src/index.ts +++ b/plugins/nodemon/src/index.ts @@ -1,3 +1,3 @@ import Nodemon from './tasks/nodemon' -export const tasks = [Nodemon] +export const tasks = { Nodemon } diff --git a/plugins/npm/.toolkitrc.yml b/plugins/npm/.toolkitrc.yml index e69de29bb..856096a25 100644 --- a/plugins/npm/.toolkitrc.yml +++ b/plugins/npm/.toolkitrc.yml @@ -0,0 +1,8 @@ +installs: + - 'build:local' + - 'test:local' + - 'run:local' + +tasks: + - NpmPrune + - NpmPublish diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts index 59fbb25e7..d77712f2e 100644 --- a/plugins/npm/src/index.ts +++ b/plugins/npm/src/index.ts @@ -31,7 +31,7 @@ export const hooks = { 'run:local': RunLocal } -export const tasks = [ +export const tasks = { NpmPrune, NpmPublish -] +} diff --git a/plugins/upload-assets-to-s3/.toolkitrc.yml b/plugins/upload-assets-to-s3/.toolkitrc.yml index c9222944d..97d28931f 100644 --- a/plugins/upload-assets-to-s3/.toolkitrc.yml +++ b/plugins/upload-assets-to-s3/.toolkitrc.yml @@ -1,2 +1,5 @@ +tasks: + - UploadAssetsToS3 + hooks: 'release:remote': UploadAssetsToS3 diff --git a/plugins/upload-assets-to-s3/src/index.ts b/plugins/upload-assets-to-s3/src/index.ts index 28d683f7a..dc8838fa5 100644 --- a/plugins/upload-assets-to-s3/src/index.ts +++ b/plugins/upload-assets-to-s3/src/index.ts @@ -1,3 +1,3 @@ import UploadAssetsToS3 from './tasks/upload-assets-to-s3' -export const tasks = [UploadAssetsToS3] +export const tasks = { UploadAssetsToS3 } diff --git a/plugins/webpack/.toolkitrc.yml b/plugins/webpack/.toolkitrc.yml index d91271130..1a60904ca 100644 --- a/plugins/webpack/.toolkitrc.yml +++ b/plugins/webpack/.toolkitrc.yml @@ -1,3 +1,8 @@ +tasks: + - WebpackDevelopment + - WebpackProduction + - WebpackWatch + hooks: 'build:local': WebpackDevelopment 'build:ci': WebpackProduction diff --git a/plugins/webpack/src/index.ts b/plugins/webpack/src/index.ts index bc5b12f99..6d60e8fca 100644 --- a/plugins/webpack/src/index.ts +++ b/plugins/webpack/src/index.ts @@ -2,4 +2,4 @@ import WebpackDevelopment from './tasks/development' import WebpackProduction from './tasks/production' import WebpackWatch from './tasks/watch' -export const tasks = [WebpackDevelopment, WebpackProduction, WebpackWatch] +export const tasks = { WebpackDevelopment, WebpackProduction, WebpackWatch } From 3781371a97c6ce1dd07e7c023069ae5313638b50 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Thu, 27 Apr 2023 11:54:55 +0100 Subject: [PATCH 002/321] perf(core): selectively load core modules based on subcommand --- core/cli/bin/run | 5 ++++- core/cli/src/index.ts | 3 --- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/cli/bin/run b/core/cli/bin/run index 22555b593..aeec5d51e 100755 --- a/core/cli/bin/run +++ b/core/cli/bin/run @@ -5,18 +5,21 @@ const argv = require('minimist')(process.argv.slice(2), { '--': true }) -const { runTasks, showHelp, installHooks, listPlugins } = require('../lib') const { rootLogger, styles } = require('@dotcom-tool-kit/logger') async function main() { try { if (argv.install) { + const installHooks = require('../lib/install').default await installHooks(rootLogger) } else if (argv.listPlugins) { + const { listPlugins } = require('../lib') await listPlugins(rootLogger) } else if (argv.help || argv._.length === 0) { + const showHelp = require('../lib/help').default await showHelp(rootLogger, argv._) } else { + const { runTasks } = require('../lib') if (argv['--'].length > 0) { // The `--` in a command such as `dotcom-tool-kit test:staged --` // delineates between hooks and file patterns. For example, when the diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 4ca648dbb..9a81727ec 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -122,6 +122,3 @@ export async function listPlugins(logger: Logger): Promise { logger.info(formatPluginTree(rootPlugin.value).join('\n')) } } - -export { default as showHelp } from './help' -export { default as installHooks } from './install' From c83420750f9282b550014ae5c3d2cc5b698fd8ca Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Thu, 12 Oct 2023 16:05:16 +0100 Subject: [PATCH 003/321] perf!: add new lazy plugin spec to rest of plugins --- plugins/babel/.toolkitrc.yml | 4 ++++ plugins/babel/src/index.ts | 2 +- plugins/circleci-npm/.toolkitrc.yml | 5 ++++- plugins/cypress/.toolkitrc.yml | 7 +++++++ plugins/cypress/src/index.ts | 2 +- plugins/jest/.toolkitrc.yml | 4 ++++ plugins/jest/src/index.ts | 4 ++-- plugins/pa11y/.toolkitrc.yml | 3 +++ plugins/pa11y/src/index.ts | 2 +- plugins/prettier/.toolkitrc.yml | 6 ++++++ plugins/prettier/src/index.ts | 2 +- plugins/serverless/.toolkitrc.yml | 4 ++++ plugins/serverless/src/index.ts | 2 +- plugins/typescript/.toolkitrc.yml | 5 +++++ plugins/typescript/src/index.ts | 2 +- 15 files changed, 45 insertions(+), 9 deletions(-) diff --git a/plugins/babel/.toolkitrc.yml b/plugins/babel/.toolkitrc.yml index a583f6fdd..bedb36ca5 100644 --- a/plugins/babel/.toolkitrc.yml +++ b/plugins/babel/.toolkitrc.yml @@ -1,3 +1,7 @@ +tasks: + - BabelDevelopment + - BabelProduction + hooks: 'build:local': BabelDevelopment 'build:ci': BabelProduction diff --git a/plugins/babel/src/index.ts b/plugins/babel/src/index.ts index 20e63ace5..c7a2f07eb 100644 --- a/plugins/babel/src/index.ts +++ b/plugins/babel/src/index.ts @@ -1,4 +1,4 @@ import BabelDevelopment from './tasks/development' import BabelProduction from './tasks/production' -export const tasks = [BabelDevelopment, BabelProduction] +export const tasks = { BabelDevelopment, BabelProduction } diff --git a/plugins/circleci-npm/.toolkitrc.yml b/plugins/circleci-npm/.toolkitrc.yml index 3cbf26a25..d40fe44e2 100644 --- a/plugins/circleci-npm/.toolkitrc.yml +++ b/plugins/circleci-npm/.toolkitrc.yml @@ -2,5 +2,8 @@ plugins: - '@dotcom-tool-kit/circleci' - '@dotcom-tool-kit/npm' +installs: + - 'publish:tag' + hooks: - 'publish:tag': NpmPublish \ No newline at end of file + 'publish:tag': NpmPublish diff --git a/plugins/cypress/.toolkitrc.yml b/plugins/cypress/.toolkitrc.yml index 3cdf0e6d6..0e879e04c 100644 --- a/plugins/cypress/.toolkitrc.yml +++ b/plugins/cypress/.toolkitrc.yml @@ -1,3 +1,10 @@ +installs: + - 'e2e:local' + +tasks: + - CypressCi + - CypressLocal + hooks: 'test:review': CypressCi 'test:staging': CypressCi diff --git a/plugins/cypress/src/index.ts b/plugins/cypress/src/index.ts index 4c773111c..eefb1970d 100644 --- a/plugins/cypress/src/index.ts +++ b/plugins/cypress/src/index.ts @@ -10,4 +10,4 @@ export const hooks = { 'e2e:local': E2ETestHook } -export const tasks = [CypressLocal, CypressCi] +export const tasks = { CypressLocal, CypressCi } diff --git a/plugins/jest/.toolkitrc.yml b/plugins/jest/.toolkitrc.yml index c87be6023..971ef1839 100644 --- a/plugins/jest/.toolkitrc.yml +++ b/plugins/jest/.toolkitrc.yml @@ -1,3 +1,7 @@ +tasks: + - JestLocal + - JestCI + hooks: 'test:local': JestLocal 'test:ci': JestCI diff --git a/plugins/jest/src/index.ts b/plugins/jest/src/index.ts index 8a6730386..844b10624 100644 --- a/plugins/jest/src/index.ts +++ b/plugins/jest/src/index.ts @@ -1,7 +1,7 @@ import JestCI from './tasks/ci' import JestLocal from './tasks/local' -export const tasks = [ +export const tasks = { JestCI, JestLocal -] +} diff --git a/plugins/pa11y/.toolkitrc.yml b/plugins/pa11y/.toolkitrc.yml index 7563f8d01..b9ff4c523 100644 --- a/plugins/pa11y/.toolkitrc.yml +++ b/plugins/pa11y/.toolkitrc.yml @@ -1,5 +1,8 @@ plugins: - '@dotcom-tool-kit/doppler' +tasks: + - Pa11y + hooks: 'test:local': Pa11y diff --git a/plugins/pa11y/src/index.ts b/plugins/pa11y/src/index.ts index 7e068ccc6..381ca3f19 100644 --- a/plugins/pa11y/src/index.ts +++ b/plugins/pa11y/src/index.ts @@ -1,3 +1,3 @@ import Pa11y from './tasks/pa11y' -export const tasks = [Pa11y] +export const tasks = { Pa11y } diff --git a/plugins/prettier/.toolkitrc.yml b/plugins/prettier/.toolkitrc.yml index d56011a80..adec8557c 100644 --- a/plugins/prettier/.toolkitrc.yml +++ b/plugins/prettier/.toolkitrc.yml @@ -1,3 +1,9 @@ +installs: + - "format:local" + +tasks: + - Prettier + hooks: 'format:local': Prettier 'format:staged': Prettier diff --git a/plugins/prettier/src/index.ts b/plugins/prettier/src/index.ts index ec8dfd00b..41e6fe25e 100644 --- a/plugins/prettier/src/index.ts +++ b/plugins/prettier/src/index.ts @@ -1,7 +1,7 @@ import { PackageJsonScriptHook } from '@dotcom-tool-kit/package-json-hook' import Prettier from './tasks/prettier' -export const tasks = [Prettier] +export const tasks = { Prettier } class FormatLocal extends PackageJsonScriptHook { static description = 'format prettier' diff --git a/plugins/serverless/.toolkitrc.yml b/plugins/serverless/.toolkitrc.yml index e69de29bb..bd06dec03 100644 --- a/plugins/serverless/.toolkitrc.yml +++ b/plugins/serverless/.toolkitrc.yml @@ -0,0 +1,4 @@ +tasks: + - ServerlessRun + - ServerlessDeploy + - ServerlessProvision diff --git a/plugins/serverless/src/index.ts b/plugins/serverless/src/index.ts index e5ae4008b..687fade58 100644 --- a/plugins/serverless/src/index.ts +++ b/plugins/serverless/src/index.ts @@ -3,4 +3,4 @@ import ServerlessProvision from './tasks/provision' import ServerlessRun from './tasks/run' import ServerlessTeardown from './tasks/teardown' -export const tasks = [ServerlessRun, ServerlessDeploy, ServerlessProvision, ServerlessTeardown] +export const tasks = { ServerlessRun, ServerlessDeploy, ServerlessProvision, ServerlessTeardown } diff --git a/plugins/typescript/.toolkitrc.yml b/plugins/typescript/.toolkitrc.yml index 5f5ed2408..a09ed8dbf 100644 --- a/plugins/typescript/.toolkitrc.yml +++ b/plugins/typescript/.toolkitrc.yml @@ -1,3 +1,8 @@ +tasks: + - TypeScriptBuild + - TypeScriptWatch + - TypeScriptTest + hooks: 'build:local': TypeScriptBuild 'build:ci': TypeScriptBuild diff --git a/plugins/typescript/src/index.ts b/plugins/typescript/src/index.ts index 41e60f3e0..d5928b163 100644 --- a/plugins/typescript/src/index.ts +++ b/plugins/typescript/src/index.ts @@ -1,3 +1,3 @@ import { TypeScriptBuild, TypeScriptWatch, TypeScriptTest } from './tasks/typescript' -export const tasks = [TypeScriptBuild, TypeScriptWatch, TypeScriptTest] +export const tasks = { TypeScriptBuild, TypeScriptWatch, TypeScriptTest } From f3dfad4da47cdf788dc4299d465177c8e1504523 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Fri, 13 Oct 2023 15:07:45 +0100 Subject: [PATCH 004/321] feat(core): run hook checks when running tasks if files have changed We avoid running checks unconditionally so that we don't have to load all plugins that export hooks every time we run a command, but we still want to let the user know if their config files have diverged from what the hooks have installed. Let's only check the configuration when running commands if we see the files have changed, storing hashes in .toolkitstate to compare. For now, the configuration files to check are hardcoded (CircleCI, package.json, and .toolkitrc.yml) but in the future we could have hooks register which files they modify and check those. --- core/cli/src/config.ts | 78 ++++++++++++++++++++++++++++++++++++++++- core/cli/src/index.ts | 4 ++- core/cli/src/install.ts | 13 +++---- lib/state/src/index.ts | 4 +++ 4 files changed, 88 insertions(+), 11 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index a5e1ddfff..97ad46e51 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -1,3 +1,6 @@ +import { createHash } from 'node:crypto' +import { readFile } from 'node:fs/promises' + import path from 'path' import type { Logger } from 'winston' @@ -5,7 +8,15 @@ import type { HookTask } from './hook' import { loadPlugin, resolvePlugin } from './plugin' import { Conflict, findConflicts, withoutConflicts, isConflict } from './conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' -import { TaskClass, Hook, mapValidated, Plugin, reduceValidated, Validated } from '@dotcom-tool-kit/types' +import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' +import { + Hook, + HookConstructor, + mapValidated, + Plugin, + reduceValidated, + Validated +} from '@dotcom-tool-kit/types' import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/schema' import { InvalidOption, @@ -57,6 +68,71 @@ export type ValidConfig = Omit[]> { + return Promise.all( + Object.entries(config.hooks).map(async ([hookName, pluginId]) => { + const plugin = await import(pluginId) + const Hook = plugin.hooks[hookName] as HookConstructor + return new Hook(logger, hookName) + }) + ) +} + +export async function fileHash(path: string): Promise { + const hashFunc = createHash('sha512') + try { + hashFunc.update(await readFile(path)) + return hashFunc.digest('base64') + } catch (error) { + if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') { + return 'n/a' + } else { + throw error + } + } +} + +export async function updateHashes(): Promise { + const hashes = Object.fromEntries( + await Promise.all(configPaths.map(async (path) => [path, await fileHash(path)])) + ) + writeState('install', hashes) +} + +async function hasConfigChanged(logger: Logger): Promise { + const hashes = readState('install') + if (!hashes) { + return true + } + for (const [path, prevHash] of Object.entries(hashes)) { + const newHash = await fileHash(path) + if (newHash !== prevHash) { + logger.debug(`hash for path ${path} has changed, running hook checks`) + return true + } + } + return false +} + +export async function checkInstall(logger: Logger, config: ValidConfig): Promise { + if (!(await hasConfigChanged(logger))) { + return + } + + const hooks = await loadHooks(logger, config) + const uninstalledHooks = await asyncFilter(hooks, async (hook) => { + return !(await hook.check()) + }) + + if (uninstalledHooks.length > 0) { + const error = new ToolKitError('There are problems with your Tool Kit installation.') + error.details = formatUninstalledHooks(uninstalledHooks) + throw error + } + + await updateHashes() +} + export const createConfig = (): RawConfig => ({ root: coreRoot, plugins: {}, diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 9a81727ec..0ce93344a 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -1,5 +1,5 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -import { loadConfig } from './config' +import { checkInstall, loadConfig } from './config' import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' @@ -53,6 +53,8 @@ ${availableHooks}` } } + await checkInstall(logger, config) + if (shouldDisableNativeFetch()) { process.execArgv.push('--no-experimental-fetch') } diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index a59359922..5fcfe23d1 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -1,9 +1,8 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' -import { Hook, HookConstructor } from '@dotcom-tool-kit/types' import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' -import { loadConfig, ValidConfig } from './config' +import { loadConfig, loadHooks, updateHashes, ValidConfig } from './config' import { postInstall } from './postInstall' // implementation of the Array.every method that supports asynchronous predicates @@ -28,13 +27,7 @@ export default async function installHooks(logger: Logger): Promise const errors: Error[] = [] // group hooks without an installGroup separately so that their check() // method runs independently - const hooks: Hook[] = await Promise.all( - Object.entries(config.hooks).map(async ([hookName, pluginId]) => { - const plugin = await import(pluginId) - const Hook = plugin.hooks[hookName] as HookConstructor - return new Hook(logger, hookName) - }) - ) + const hooks = await loadHooks(logger, config) const groups = groupBy(hooks, (hook) => hook.installGroup ?? '__' + hook.id) for (const group of Object.values(groups)) { try { @@ -79,5 +72,7 @@ export default async function installHooks(logger: Logger): Promise throw error } + await updateHashes() + return config } diff --git a/lib/state/src/index.ts b/lib/state/src/index.ts index daebf5baf..62b14747e 100644 --- a/lib/state/src/index.ts +++ b/lib/state/src/index.ts @@ -4,6 +4,9 @@ import * as fs from 'fs' const target = process.env.INIT_CWD || process.cwd() const stateDir = target ? path.join(target, '.toolkitstate') : '.toolkitstate' +export const configPaths = ['.toolkitrc.yml', 'package.json', '.circleci/config.yml'] as const +type InstallState = Record + interface CIState { repo: string branch: string @@ -39,6 +42,7 @@ export interface State { staging: StagingState production: ProductionState local: LocalState + install: InstallState } export function readState(stage: T): State[T] | null { From 56f664901a274e924e2e0cb63c9799049d967a64 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 7 Nov 2023 12:32:30 +0000 Subject: [PATCH 005/321] refactor: extract an unwrapValidated for the pattern of "return value if valid, throw if not" --- core/cli/src/config.ts | 16 +++------------- lib/types/src/index.ts | 11 +++++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 97ad46e51..97fd075ae 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -15,6 +15,7 @@ import { mapValidated, Plugin, reduceValidated, + unwrapValidated, Validated } from '@dotcom-tool-kit/types' import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/schema' @@ -296,21 +297,10 @@ export async function loadConfig(logger: Logger, { validate = true } = {}): Prom // start loading config and child plugins, starting from the consumer app directory const rootPlugin = await loadPlugin('app root', config, logger) - if (!rootPlugin.valid) { - const error = new ToolKitError('root plugin was not valid!') - error.details = rootPlugin.reasons.join('\n\n') - throw error - } - const validRootPlugin = rootPlugin.value + const validRootPlugin = unwrapValidated(rootPlugin, 'root plugin was not valid!') const validatedPluginConfig = validatePlugins(config) - - if (!validatedPluginConfig.valid) { - const error = new ToolKitError('config was not valid!') - error.details = validatedPluginConfig.reasons.join('\n\n') - throw error - } - const validPluginConfig = validatedPluginConfig.value + const validPluginConfig = unwrapValidated(validatedPluginConfig, 'config was not valid!') // collate root plugin and descendent hooks, options etc into config resolvePlugin(validRootPlugin, validPluginConfig, logger) diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 633ab1309..4546a97ec 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -1,3 +1,4 @@ +import { ToolKitError } from '@dotcom-tool-kit/error' import { styles as s } from '@dotcom-tool-kit/logger' import fs from 'fs' import path from 'path' @@ -81,6 +82,16 @@ export function reduceValidated(validated: Validated[]): Validated { return sequenced } +export function unwrapValidated(validated: Validated, message = ''): T { + if (validated.valid) { + return validated.value + } else { + const error = new ToolKitError(message) + error.details = validated.reasons.join('\n\n') + throw error + } +} + abstract class Base { static version = version version = version From 7bcc0a59cf7a6d8a1425b89502c61fe4af9e102d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 7 Nov 2023 17:09:55 +0000 Subject: [PATCH 006/321] =?UTF-8?q?feat:=20re=C3=AFntroduce=20validating?= =?UTF-8?q?=20plugins=20when=20we=20load=20them?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/cli/src/config.ts | 27 +++++++------ core/cli/src/index.ts | 49 +++++++++++++++-------- core/cli/src/install.ts | 4 +- core/cli/src/plugin.ts | 88 +++++++++++++++++++++++++++++++++++++++++ lib/types/src/index.ts | 23 ++++++++++- 5 files changed, 160 insertions(+), 31 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 97fd075ae..6a6ccd8de 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -5,13 +5,13 @@ import path from 'path' import type { Logger } from 'winston' import type { HookTask } from './hook' -import { loadPlugin, resolvePlugin } from './plugin' +import { RawPluginModule, importPlugin, loadPlugin, resolvePlugin, validatePluginHooks } from './plugin' import { Conflict, findConflicts, withoutConflicts, isConflict } from './conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' import { + flatMapValidated, Hook, - HookConstructor, mapValidated, Plugin, reduceValidated, @@ -69,15 +69,19 @@ export type ValidConfig = Omit[]> { - return Promise.all( - Object.entries(config.hooks).map(async ([hookName, pluginId]) => { - const plugin = await import(pluginId) - const Hook = plugin.hooks[hookName] as HookConstructor - return new Hook(logger, hookName) - }) +export const loadHooks = async (logger: Logger, config: ValidConfig): Promise[]>> => + reduceValidated( + await Promise.all( + Object.entries(config.hooks).map(async ([hookName, pluginId]) => + flatMapValidated(await importPlugin(pluginId), (plugin) => + mapValidated( + validatePluginHooks(plugin as RawPluginModule), + (hooks) => new hooks[hookName](logger, hookName) + ) + ) + ) + ) ) -} export async function fileHash(path: string): Promise { const hashFunc = createHash('sha512') @@ -120,7 +124,8 @@ export async function checkInstall(logger: Logger, config: ValidConfig): Promise return } - const hooks = await loadHooks(logger, config) + const hooks = unwrapValidated(await loadHooks(logger, config), 'hooks are invalid') + const uninstalledHooks = await asyncFilter(hooks, async (hook) => { return !(await hook.check()) }) diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 0ce93344a..a8c74a27f 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -1,10 +1,18 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -import { checkInstall, loadConfig } from './config' +import { ValidConfig, checkInstall, loadConfig } from './config' import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' import { formatPluginTree } from './messages' -import { TaskClass } from '@dotcom-tool-kit/types' +import { + Task, + Validated, + flatMapValidated, + mapValidated, + reduceValidated, + unwrapValidated +} from '@dotcom-tool-kit/types' +import { RawPluginModule, importPlugin, validatePluginTasks } from './plugin' type ErrorSummary = { hook: string @@ -28,6 +36,23 @@ export const shouldDisableNativeFetch = (): boolean => { ) } +const loadTasks = async (logger: Logger, config: ValidConfig): Promise>> => + mapValidated( + reduceValidated( + await Promise.all( + Object.entries(config.tasks).map(async ([taskName, pluginId]) => + flatMapValidated(await importPlugin(pluginId), (plugin) => + mapValidated(validatePluginTasks(plugin as RawPluginModule), (tasks) => [ + taskName, + new tasks[taskName](logger, taskName, getOptions(pluginId as OptionKey) ?? {}) + ]) + ) + ) + ) + ), + Object.fromEntries + ) + export async function runTasks(logger: Logger, hooks: string[], files?: string[]): Promise { const config = await loadConfig(logger) @@ -59,6 +84,8 @@ ${availableHooks}` process.execArgv.push('--no-experimental-fetch') } + const tasks = unwrapValidated(await loadTasks(logger, config), 'tasks are invalid') + for (const hook of hooks) { const errors: ErrorSummary[] = [] @@ -66,23 +93,11 @@ ${availableHooks}` logger.warn(`no task configured for ${hook}: skipping assignment...`) continue } - const assignment = config.hookTasks[hook] - - for (const id of assignment.tasks) { - const pluginId = config.tasks[id] - const Task = (await import(pluginId)).tasks[id] as TaskClass - - const options = getOptions(pluginId as OptionKey) - - /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- - * `Task` is an abstract class. Here we know it's a concrete subclass - * but typescript doesn't, so cast it to any. - **/ - const task = new (Task as any)(logger, id, options) - logger.info(styles.taskHeader(`running ${styles.task(id)} task`)) + for (const id of config.hookTasks[hook].tasks) { try { - await task.run(files) + logger.info(styles.taskHeader(`running ${styles.task(id)} task`)) + await tasks[id].run(files) } catch (error) { // allow subsequent hook tasks to run on error errors.push({ diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 5fcfe23d1..b0dee9e6f 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -4,6 +4,7 @@ import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' import { loadConfig, loadHooks, updateHashes, ValidConfig } from './config' import { postInstall } from './postInstall' +import { unwrapValidated } from '@dotcom-tool-kit/types' // implementation of the Array.every method that supports asynchronous predicates async function asyncEvery(arr: T[], pred: (x: T) => Promise): Promise { @@ -27,7 +28,8 @@ export default async function installHooks(logger: Logger): Promise const errors: Error[] = [] // group hooks without an installGroup separately so that their check() // method runs independently - const hooks = await loadHooks(logger, config) + const hooks = unwrapValidated(await loadHooks(logger, config), 'hooks are invalid') + const groups = groupBy(hooks, (hook) => hook.installGroup ?? '__' + hook.id) for (const group of Object.values(groups)) { try { diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index ca77997a5..ec1dc6d17 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,9 +1,12 @@ import { styles as s } from '@dotcom-tool-kit/logger' import { + Hook, mapValidated, mapValidationError, Plugin, + PluginModule, reduceValidated, + Task, Valid, Validated } from '@dotcom-tool-kit/types' @@ -13,6 +16,7 @@ import { PluginOptions, RawConfig, ValidPluginsConfig } from './config' import { Conflict, isConflict } from './conflict' import type { HookTask } from './hook' import { loadToolKitRC } from './rc-file' +import { isPlainObject } from 'lodash' function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { if (!possibleDescendent.parent) { @@ -24,6 +28,88 @@ function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boo } } +const isPlainObjectGuard = (value: unknown): value is Record => isPlainObject(value) + +export type RawPluginModule = Partial + +export function validatePluginTasks(plugin: RawPluginModule): Validated { + if (plugin.tasks) { + if (!isPlainObjectGuard(plugin.tasks)) { + return { + valid: false, + reasons: [`the exported ${s.code('tasks')} value from this plugin is not an object`] + } + } else { + return mapValidated( + reduceValidated( + Object.entries(plugin.tasks).map(([id, task]) => + mapValidationError( + mapValidated(Task.isCompatible(task), (task) => [id, task]), + (reasons) => [ + `the task ${s.task(task.name)} is not a compatible instance of ${s.code( + 'Task' + )}:\n - ${reasons.join('\n - ')}` + ] + ) + ) + ), + Object.fromEntries + ) + } + } + + return { valid: true, value: {} } +} + +export function validatePluginHooks(plugin: RawPluginModule): Validated { + if (plugin.hooks) { + if (!isPlainObjectGuard(plugin.hooks)) { + return { + valid: false, + reasons: [`the exported ${s.code('hooks')} value from this plugin is not an object`] + } + } else { + return mapValidated( + reduceValidated( + Object.entries(plugin.hooks).map(([id, hook]) => + mapValidationError( + mapValidated(Hook.isCompatible(hook), (hook) => [id, hook]), + (reasons) => [ + `the hook ${s.hook(id)} is not a compatible instance of ${s.code( + 'Hook' + )}:\n - ${reasons.join('\n - ')}` + ] + ) + ) + ), + Object.fromEntries + ) + } + } + return { valid: true, value: {} } +} + +export async function importPlugin(pluginPath: string): Promise> { + try { + // pluginPath is an absolute resolved path to a plugin module as found from its parent + const pluginModule: unknown = await import(pluginPath) + return { + valid: true, + value: pluginModule + } + } catch (e) { + const err = e as Error + return { + valid: false, + reasons: [ + `an error was thrown when loading this plugin's entrypoint:\n ${s.code( + indentReasons(err.toString()) + )}` + ] + } + } +} + const indentReasons = (reasons: string): string => reasons.replace(/\n/g, '\n ') export async function loadPlugin( @@ -59,6 +145,8 @@ export async function loadPlugin( config.plugins[id] = plugin + // ESlint disable explanation: erroring due to a possible race condition but is a false positive since the plugin variable isn't from another scope and can't be written to concurrently. + // eslint-disable-next-line require-atomic-updates plugin.value.rcFile = await loadToolKitRC(logger, pluginRoot, isAppRoot) const children = await Promise.all( diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 4546a97ec..55f13d9b8 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -82,6 +82,14 @@ export function reduceValidated(validated: Validated[]): Validated { return sequenced } +export function flatMapValidated(validated: Validated, f: (val: T) => Validated): Validated { + if (validated.valid) { + return f(validated.value) + } else { + return validated + } +} + export function unwrapValidated(validated: Validated, message = ''): T { if (validated.valid) { return validated.value @@ -172,9 +180,11 @@ export abstract class Task extends Base { abstract run(files?: string[]): Promise } -export type TaskClass = { +export type TaskConstructor = { new (logger: Logger, id: string, options: Partial>): Task -} & typeof Task +} + +export type TaskClass = TaskConstructor & typeof Task export abstract class Hook extends Base { logger: Logger @@ -227,3 +237,12 @@ export interface Plugin { parent?: Plugin children?: Plugin[] } + +export interface PluginModule { + tasks: { + [id: string]: TaskConstructor + } + hooks: { + [id: string]: HookConstructor + } +} From c34fa7b56d92133b5139834515757736f92e45d8 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 9 Nov 2023 09:26:23 +0000 Subject: [PATCH 007/321] test: reinstate plugin validity test --- core/cli/test/plugin.test.js | 25 ------------------------- core/cli/test/plugin.test.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 25 deletions(-) delete mode 100644 core/cli/test/plugin.test.js create mode 100644 core/cli/test/plugin.test.ts diff --git a/core/cli/test/plugin.test.js b/core/cli/test/plugin.test.js deleted file mode 100644 index 8fc5e6b57..000000000 --- a/core/cli/test/plugin.test.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * File must be JavaScript as ts-jest transform breaks instanceof Hook test in - * instantiatePlugin function, apparently comparing two different versions of - * the Hook constructor when going up the plugin's prototype chain. - */ -const { describe, it } = require('@jest/globals') -const fs = require('fs') -const path = require('path') -const winston = require('winston') -const { validatePlugin } = require('../lib/plugin') - -const pluginDir = path.join(__dirname, '../../../plugins') - -function getPlugins() { - const pluginDirContents = fs.readdirSync(pluginDir, { withFileTypes: true }) - return pluginDirContents.filter((plugin) => plugin.isDirectory()).map((plugin) => plugin.name) -} - -describe.each(getPlugins())('%s integration test', (plugin) => { - const packagePath = path.join(pluginDir, plugin) - it('should be a valid plugin', () => { - const pluginPackage = require(packagePath) - validatePlugin(pluginPackage, winston) - }) -}) diff --git a/core/cli/test/plugin.test.ts b/core/cli/test/plugin.test.ts new file mode 100644 index 000000000..f9ac9a22b --- /dev/null +++ b/core/cli/test/plugin.test.ts @@ -0,0 +1,31 @@ +import { describe, it } from '@jest/globals' +import fs from 'fs' +import path from 'path' +import { RawPluginModule, importPlugin, validatePluginHooks, validatePluginTasks } from '../src/plugin' +import { unwrapValidated } from '@dotcom-tool-kit/types' + +const pluginDir = path.join(__dirname, '../../../plugins') + +function getPlugins() { + const pluginDirContents = fs.readdirSync(pluginDir, { withFileTypes: true }) + return pluginDirContents.filter((plugin) => plugin.isDirectory()).map((plugin) => plugin.name) +} + +describe.each(getPlugins())('%s integration test', (pluginName) => { + const packagePath = path.join(pluginDir, pluginName) + let plugin: RawPluginModule + + beforeAll(async () => { + plugin = unwrapValidated(await importPlugin(packagePath)) as RawPluginModule + }) + + it('should have valid tasks', () => { + const tasks = validatePluginTasks(plugin) + expect(tasks).not.toHaveProperty('reasons') + }) + + it('should have valid hooks', () => { + const hooks = validatePluginHooks(plugin) + expect(hooks).not.toHaveProperty('reasons') + }) +}) From c49c70d544e8f773002d5c0251ff9802619f3956 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 9 Nov 2023 13:06:35 +0000 Subject: [PATCH 008/321] chore: replace empty tasks exports with nothing --- plugins/backend-app/index.js | 1 - plugins/backend-heroku-app/index.js | 1 - plugins/backend-serverless-app/index.js | 1 - plugins/circleci-heroku/index.js | 1 - plugins/component/index.js | 1 - plugins/frontend-app/index.js | 1 - 6 files changed, 6 deletions(-) diff --git a/plugins/backend-app/index.js b/plugins/backend-app/index.js index 2793ef369..e69de29bb 100644 --- a/plugins/backend-app/index.js +++ b/plugins/backend-app/index.js @@ -1 +0,0 @@ -exports.tasks = [] \ No newline at end of file diff --git a/plugins/backend-heroku-app/index.js b/plugins/backend-heroku-app/index.js index c32ed7534..e69de29bb 100644 --- a/plugins/backend-heroku-app/index.js +++ b/plugins/backend-heroku-app/index.js @@ -1 +0,0 @@ -exports.tasks = [] diff --git a/plugins/backend-serverless-app/index.js b/plugins/backend-serverless-app/index.js index c32ed7534..e69de29bb 100644 --- a/plugins/backend-serverless-app/index.js +++ b/plugins/backend-serverless-app/index.js @@ -1 +0,0 @@ -exports.tasks = [] diff --git a/plugins/circleci-heroku/index.js b/plugins/circleci-heroku/index.js index c32ed7534..e69de29bb 100644 --- a/plugins/circleci-heroku/index.js +++ b/plugins/circleci-heroku/index.js @@ -1 +0,0 @@ -exports.tasks = [] diff --git a/plugins/component/index.js b/plugins/component/index.js index c32ed7534..e69de29bb 100644 --- a/plugins/component/index.js +++ b/plugins/component/index.js @@ -1 +0,0 @@ -exports.tasks = [] diff --git a/plugins/frontend-app/index.js b/plugins/frontend-app/index.js index c32ed7534..e69de29bb 100644 --- a/plugins/frontend-app/index.js +++ b/plugins/frontend-app/index.js @@ -1 +0,0 @@ -exports.tasks = [] From b82fc5abecebc867e437a6a7b8db99cc508979a6 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 9 Nov 2023 13:09:32 +0000 Subject: [PATCH 009/321] test: pass ids in when instantiating tasks for tests --- plugins/babel/test/tasks/babel.test.ts | 2 +- plugins/eslint/test/tasks/eslint.test.ts | 4 +- plugins/heroku/test/tasks/production.test.ts | 7 ++- plugins/heroku/test/tasks/review.test.ts | 26 +++------ plugins/heroku/test/tasks/staging.test.ts | 56 +++---------------- plugins/jest/tests/jest-plugin.test.ts | 8 +-- plugins/mocha/test/tasks/mocha.test.ts | 4 +- plugins/n-test/test/tasks/n-test.test.ts | 6 +- plugins/pa11y/test/pa11y.test.ts | 4 +- plugins/prettier/test/tasks/prettier.test.ts | 6 +- .../typescript/test/tasks/typescript.test.ts | 8 +-- .../test/tasks/upload-assets-to-s3.test.ts | 12 ++-- plugins/webpack/test/tasks/webpack.test.ts | 8 +-- 13 files changed, 52 insertions(+), 99 deletions(-) diff --git a/plugins/babel/test/tasks/babel.test.ts b/plugins/babel/test/tasks/babel.test.ts index 94ab2ca78..21d91557d 100644 --- a/plugins/babel/test/tasks/babel.test.ts +++ b/plugins/babel/test/tasks/babel.test.ts @@ -17,7 +17,7 @@ describe('babel', () => { }) it('should transpile the file', async () => { - const task = new Babel(logger, { + const task = new Babel(logger, 'Babel', { files: path.join(testDirectory, 'index.js'), outputPath, configFile: path.join(testDirectory, 'babel.config.json') diff --git a/plugins/eslint/test/tasks/eslint.test.ts b/plugins/eslint/test/tasks/eslint.test.ts index d0e412284..789b7a380 100644 --- a/plugins/eslint/test/tasks/eslint.test.ts +++ b/plugins/eslint/test/tasks/eslint.test.ts @@ -10,7 +10,7 @@ const testDirectory = path.join(__dirname, '../files') describe('eslint', () => { it('should pass on correct file', async () => { - const task = new ESLint(logger, { + const task = new ESLint(logger, 'ESLint', { options: { ignore: false, cwd: testDirectory }, files: [path.join(testDirectory, 'pass.js')] }) @@ -19,7 +19,7 @@ describe('eslint', () => { }) it('should fail on linter error', async () => { - const task = new ESLint(logger, { + const task = new ESLint(logger, 'ESLint', { options: { ignore: false, cwd: testDirectory }, files: [path.join(testDirectory, 'fail.js')] }) diff --git a/plugins/heroku/test/tasks/production.test.ts b/plugins/heroku/test/tasks/production.test.ts index 91345b45f..5765317fd 100644 --- a/plugins/heroku/test/tasks/production.test.ts +++ b/plugins/heroku/test/tasks/production.test.ts @@ -16,6 +16,7 @@ const mockPromoteStagingToProduction = jest.spyOn(utils, 'promoteStagingToProduc jest.spyOn(Production.prototype, 'fetchIfAppHasDeployed').mockImplementation(() => Promise.resolve(true)) const productionOptions = { + pipeline: 'next-health', systemCode: 'next-health', scaling: { 'test-app': { web: { size: 'standard-1x', quantity: 1 } } } } @@ -23,20 +24,20 @@ const productionOptions = { describe('staging', () => { it('should call set slug with slug id and system code', async () => { mockPromoteStagingToProduction.mockImplementation(() => Promise.resolve([])) - const task = new Production(logger, productionOptions) + const task = new Production(logger, 'HerokuProduction', productionOptions) await task.run() expect(utils.promoteStagingToProduction).toBeCalledWith(expect.anything(), 'slug-id', 'next-health') }) it('should resolve when completed successfully', async () => { - const task = new Production(logger, productionOptions) + const task = new Production(logger, 'HerokuProduction', productionOptions) await expect(task.run()).resolves.not.toThrow() }) it('should throw if it completes unsuccessfully', async () => { mockPromoteStagingToProduction.mockImplementation(() => Promise.reject()) - const task = new Production(logger, productionOptions) + const task = new Production(logger, 'HerokuProduction', productionOptions) await expect(task.run()).rejects.toThrowError() }) }) diff --git a/plugins/heroku/test/tasks/review.test.ts b/plugins/heroku/test/tasks/review.test.ts index 2cec3d68a..26e4e0b7f 100644 --- a/plugins/heroku/test/tasks/review.test.ts +++ b/plugins/heroku/test/tasks/review.test.ts @@ -59,18 +59,8 @@ jest.mock('../../src/gtg', () => { }) describe('review', () => { - it('should fail when pipeline option is missing', async () => { - const task = new Review(logger, {}) - - try { - await task.run() - } catch (err) { - expect(err).toBeTruthy() - } - }) - it('should call pass in the pipeline id to heroku api call', async () => { - const task = new Review(logger, { pipeline }) + const task = new Review(logger, 'HerokuReview', { pipeline, systemCode: '', scaling: {} }) await task.run() @@ -79,7 +69,7 @@ describe('review', () => { }) it('should return review app id from get heroku review app', async () => { - const task = new Review(logger, { pipeline }) + const task = new Review(logger, 'HerokuReview', { pipeline, systemCode: '', scaling: {} }) await task.run() @@ -88,7 +78,7 @@ describe('review', () => { }) it('should fail if either doppler option is missing', async () => { - let task = new Review(logger, { pipeline }) + let task = new Review(logger, 'HerokuReview', { pipeline, systemCode: '', scaling: {} }) try { await task.run() @@ -96,7 +86,7 @@ describe('review', () => { expect(err).toBeTruthy() } - task = new Review(logger, { pipeline }) + task = new Review(logger, 'HerokuReview', { pipeline, systemCode: '', scaling: {} }) try { await task.run() @@ -106,7 +96,7 @@ describe('review', () => { }) it('should call setStageConfigVars with doppler project', async () => { - const task = new Review(logger, { pipeline }) + const task = new Review(logger, 'HerokuReview', { pipeline, systemCode: '', scaling: {} }) await task.run() @@ -114,7 +104,7 @@ describe('review', () => { }) it('should write app id to state', async () => { - const task = new Review(logger, { pipeline }) + const task = new Review(logger, 'HerokuReview', { pipeline, systemCode: '', scaling: {} }) await task.run() @@ -122,7 +112,7 @@ describe('review', () => { }) it('should call gtg with appName', async () => { - const task = new Review(logger, { pipeline }) + const task = new Review(logger, 'HerokuReview', { pipeline, systemCode: '', scaling: {} }) await task.run() @@ -131,7 +121,7 @@ describe('review', () => { it('should throw an error if it fails', async () => { pipeline = 'wrong-pipeline-name' - const task = new Review(logger, { pipeline }) + const task = new Review(logger, 'HerokuReview', { pipeline, systemCode: '', scaling: {} }) try { await task.run() diff --git a/plugins/heroku/test/tasks/staging.test.ts b/plugins/heroku/test/tasks/staging.test.ts index bddf410ae..6fdad4479 100644 --- a/plugins/heroku/test/tasks/staging.test.ts +++ b/plugins/heroku/test/tasks/staging.test.ts @@ -75,36 +75,8 @@ describe('staging', () => { buildInfo.slug = null }) - it('should fail when both options are missing', async () => { - const task = new Staging(logger, {}) - - try { - await task.run() - } catch (err) { - expect(err).toBeTruthy() - } - }) - - it('should fail if either option is missing', async () => { - let task = new Staging(logger, { pipeline }) - - try { - await task.run() - } catch (err) { - expect(err).toBeTruthy() - } - - task = new Staging(logger, { pipeline, systemCode }) - - try { - await task.run() - } catch (err) { - expect(err).toBeTruthy() - } - }) - it('should call pipeline couplings with pipeline option', async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await task.run() @@ -113,7 +85,7 @@ describe('staging', () => { }) it('should return appName from get heroku staging', async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await task.run() @@ -122,7 +94,7 @@ describe('staging', () => { }) it('should call setAppConfigVars with doppler project and system code', async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await task.run() @@ -130,7 +102,7 @@ describe('staging', () => { }) it('should call createBuild with app name', async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await task.run() @@ -138,21 +110,21 @@ describe('staging', () => { }) it(`should call repeatedCheckForBuildSuccess if the slug id isn't present`, async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await task.run() expect(repeatedCheckForBuildSuccess).toBeCalledWith(expect.anything(), appName, buildInfo.id) }) it('should call setStagingSlug with app name and slug id', async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await task.run() expect(setStagingSlug).toBeCalledWith(expect.anything(), appName, slugId) }) it('should call scaleDyno', async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await task.run() @@ -160,25 +132,15 @@ describe('staging', () => { }) it('should call gtg with appName', async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await task.run() expect(gtg).toBeCalledWith(expect.anything(), appName, 'staging') }) - it('should throw an error if it fails', async () => { - const task = new Staging(logger, { pipeline }) - - try { - await task.run() - } catch (err) { - expect(err).toBeTruthy() - } - }) - it('should resolve successfully when complete', async () => { - const task = new Staging(logger, { pipeline, systemCode }) + const task = new Staging(logger, 'HerokuStaging', { pipeline, systemCode, scaling: {} }) await expect(task.run()).resolves.not.toThrow() }) diff --git a/plugins/jest/tests/jest-plugin.test.ts b/plugins/jest/tests/jest-plugin.test.ts index 0edb1c7a9..2a28d4e19 100644 --- a/plugins/jest/tests/jest-plugin.test.ts +++ b/plugins/jest/tests/jest-plugin.test.ts @@ -21,7 +21,7 @@ jest.mock('@dotcom-tool-kit/logger') describe('jest plugin', () => { describe('local', () => { it('should call jest cli with configPath if configPath is passed in', async () => { - const jestLocal = new JestLocal(logger, { configPath: './src/jest.config.js' }) + const jestLocal = new JestLocal(logger, 'JestLocal', { configPath: './src/jest.config.js' }) await jestLocal.run() expect(fork).toBeCalledWith( @@ -34,7 +34,7 @@ describe('jest plugin', () => { }) it('should call jest cli without configPath by default', async () => { - const jestLocal = new JestLocal(logger, {}) + const jestLocal = new JestLocal(logger, 'JestLocal', {}) await jestLocal.run() expect(fork).toBeCalledWith( @@ -47,7 +47,7 @@ describe('jest plugin', () => { describe('ci', () => { it('should call jest cli with configPath if configPath is passed in', async () => { - const jestCI = new JestCI(logger, { configPath: './src/jest.config.js' }) + const jestCI = new JestCI(logger, 'JestCI', { configPath: './src/jest.config.js' }) await jestCI.run() expect(fork).toBeCalledWith( @@ -60,7 +60,7 @@ describe('jest plugin', () => { }) it('should call jest cli without configPath by default', async () => { - const jestCI = new JestCI(logger, {}) + const jestCI = new JestCI(logger, 'JestCI', {}) await jestCI.run() expect(fork).toBeCalledWith( diff --git a/plugins/mocha/test/tasks/mocha.test.ts b/plugins/mocha/test/tasks/mocha.test.ts index c22e83788..0096b535f 100644 --- a/plugins/mocha/test/tasks/mocha.test.ts +++ b/plugins/mocha/test/tasks/mocha.test.ts @@ -9,7 +9,7 @@ const logger = (winston as unknown) as Logger describe('mocha', () => { it('should succeed with passing tests', async () => { - const task = new Mocha(logger, { + const task = new Mocha(logger, 'Mocha', { files: path.resolve(__dirname, '../files/pass') + '/**/*.js' }) @@ -17,7 +17,7 @@ describe('mocha', () => { }) it('should throw with failing tests', async () => { - const task = new Mocha(logger, { + const task = new Mocha(logger, 'Mocha', { files: path.resolve(__dirname, '../files/fail') + '/**/*.js' }) diff --git a/plugins/n-test/test/tasks/n-test.test.ts b/plugins/n-test/test/tasks/n-test.test.ts index 16bf80c2b..4546aa957 100644 --- a/plugins/n-test/test/tasks/n-test.test.ts +++ b/plugins/n-test/test/tasks/n-test.test.ts @@ -13,7 +13,7 @@ const configPath = path.relative('', configAbsolutePath) describe('n-test', () => { it('should pass when no errors', async () => { - const task = new NTest(logger, { + const task = new NTest(logger, 'NTest', { config: configPath }) @@ -21,7 +21,7 @@ describe('n-test', () => { }) it('should fail when there are errors', async () => { - const task = new NTest(logger, { + const task = new NTest(logger, 'NTest', { config: configPath }) @@ -38,7 +38,7 @@ describe('n-test', () => { it('should get app url from state', async () => { const appUrl = 'https://some-test-app.herokuapp.com' writeState('review', { url: appUrl }) - const task = new NTest(logger, { + const task = new NTest(logger, 'NTest', { config: configPath }) diff --git a/plugins/pa11y/test/pa11y.test.ts b/plugins/pa11y/test/pa11y.test.ts index 77d9a2bdc..f65d6cded 100644 --- a/plugins/pa11y/test/pa11y.test.ts +++ b/plugins/pa11y/test/pa11y.test.ts @@ -35,14 +35,14 @@ describe('pa11y', () => { }) it("sets process.env.TEST_URL as a herokuapp url if readState('review') is truthy", async () => { MOCK_ENV = 'ci' - const pa11y = new Pa11y(logger, {}) + const pa11y = new Pa11y(logger, 'Pa11y', {}) await pa11y.run() expect(process.env.TEST_URL).toBe(`https://${appName}.herokuapp.com`) }) it("sets process.env.TEST_URL as a local env url if readState('local') is truthy", async () => { MOCK_ENV = 'local' - const pa11y = new Pa11y(logger, {}) + const pa11y = new Pa11y(logger, 'Pa11y', {}) await pa11y.run() expect(process.env.TEST_URL).toBe(`https://local.ft.com:5050`) diff --git a/plugins/prettier/test/tasks/prettier.test.ts b/plugins/prettier/test/tasks/prettier.test.ts index 85d3aff0b..47ea310e5 100644 --- a/plugins/prettier/test/tasks/prettier.test.ts +++ b/plugins/prettier/test/tasks/prettier.test.ts @@ -43,7 +43,7 @@ describe('prettier', () => { }) it('should format the correct file with default configOptions', async () => { - const task = new Prettier(logger, { + const task = new Prettier(logger, 'Prettier', { files: [path.join(testDirectory, 'unformatted.ts')], ignoreFile: 'nonexistent prettierignore', configOptions: defaultConfig @@ -55,7 +55,7 @@ describe('prettier', () => { it('should use configFile if present', async () => { // having the configuration file be named .prettierrc-test.json hides it from being found by prettier on other non-test occasions. - const task = new Prettier(logger, { + const task = new Prettier(logger, 'Prettier', { files: [path.join(testDirectory, 'unformatted.ts')], configFile: path.join(__dirname, '../.prettierrc-test.json'), ignoreFile: 'nonexistent prettierignore', @@ -67,7 +67,7 @@ describe('prettier', () => { }) it('should use configOptions if configFile not found', async () => { - const task = new Prettier(logger, { + const task = new Prettier(logger, 'Prettier', { files: [path.join(testDirectory, 'unformatted.ts')], configFile: '/incorrect/.prettierrc.js', ignoreFile: 'nonexistent prettierignore', diff --git a/plugins/typescript/test/tasks/typescript.test.ts b/plugins/typescript/test/tasks/typescript.test.ts index f52fef97e..a733c7a2e 100644 --- a/plugins/typescript/test/tasks/typescript.test.ts +++ b/plugins/typescript/test/tasks/typescript.test.ts @@ -24,21 +24,21 @@ const configPath = 'tsconfig.json' describe('typescript', () => { describe('correct arguments', () => { it('should start tsc build with correct arguments', async () => { - const task = new TypeScriptBuild(logger, { configPath }) + const task = new TypeScriptBuild(logger, 'TypeScriptBuild', { configPath }) await task.run() expect(fork).toBeCalledWith(tscPath, ['--project', configPath], { silent: true }) }) it('should start tsc watch with correct arguments', async () => { - const task = new TypeScriptWatch(logger, { configPath }) + const task = new TypeScriptWatch(logger, 'TypeScriptWatch', { configPath }) await task.run() expect(fork).toBeCalledWith(tscPath, ['--project', configPath, '--watch'], { silent: true }) }) it('should start tsc test with correct arguments', async () => { - const task = new TypeScriptTest(logger, { configPath }) + const task = new TypeScriptTest(logger, 'TypeScriptTest', { configPath }) await task.run() expect(fork).toBeCalledWith(tscPath, ['--project', configPath, '--noEmit'], { silent: true }) @@ -46,7 +46,7 @@ describe('typescript', () => { it('should pass in extra arguments', async () => { const extraArgs = ['--verbose', '--force'] - const task = new TypeScriptBuild(logger, { configPath, extraArgs }) + const task = new TypeScriptBuild(logger, 'TypeScriptBuild', { configPath, extraArgs }) await task.run() expect(fork).toBeCalledWith(tscPath, ['--project', configPath, ...extraArgs], { diff --git a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts index 7dfce346b..bbae7e63b 100644 --- a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts +++ b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts @@ -32,7 +32,7 @@ describe('upload-assets-to-s3', () => { }) it('should upload all globbed files for review', async () => { - const task = new UploadAssetsToS3(logger, { + const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { ...defaults, directory: testDirectory }) @@ -45,7 +45,7 @@ describe('upload-assets-to-s3', () => { }) it('should upload all globbed files for prod', async () => { - const task = new UploadAssetsToS3(logger, { + const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { ...defaults, directory: testDirectory }) @@ -58,7 +58,7 @@ describe('upload-assets-to-s3', () => { }) it('should strip base path from S3 key', async () => { - const task = new UploadAssetsToS3(logger, { + const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { ...defaults, extensions: 'gz', directory: testDirectory, @@ -73,7 +73,7 @@ describe('upload-assets-to-s3', () => { }) it('should use correct Content-Encoding for compressed files', async () => { - const task = new UploadAssetsToS3(logger, { + const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { ...defaults, extensions: 'gz', directory: testDirectory @@ -93,7 +93,7 @@ describe('upload-assets-to-s3', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any ;(mockedS3Client.prototype.send as any).mockRejectedValue(new Error(mockError)) - const task = new UploadAssetsToS3(logger, { + const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { ...defaults, directory: testDirectory }) @@ -108,7 +108,7 @@ describe('upload-assets-to-s3', () => { // HACK:20231006:IM make sure hack to support Doppler migration works it('should fallback to uppercase environment variable', async () => { - const task = new UploadAssetsToS3(logger, { + const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { ...defaults, directory: testDirectory }) diff --git a/plugins/webpack/test/tasks/webpack.test.ts b/plugins/webpack/test/tasks/webpack.test.ts index a458f3da0..04fc5e206 100644 --- a/plugins/webpack/test/tasks/webpack.test.ts +++ b/plugins/webpack/test/tasks/webpack.test.ts @@ -26,7 +26,7 @@ describe('webpack', () => { describe('development', () => { it('should call webpack cli with correct arguments', async () => { const configPath = 'webpack.config.js' - const task = new DevelopmentWebpack(logger, { configPath }) + const task = new DevelopmentWebpack(logger, 'DevelopmentWebpack', { configPath }) await task.run() expect(fork).toBeCalledWith( @@ -40,7 +40,7 @@ describe('webpack', () => { describe('production', () => { it('should call webpack cli with correct arguments', async () => { const configPath = 'webpack.config.js' - const task = new ProductionWebpack(logger, { configPath }) + const task = new ProductionWebpack(logger, 'ProductionWebpack', { configPath }) await task.run() expect(fork).toBeCalledWith( @@ -57,7 +57,7 @@ describe('webpack', () => { process.allowedNodeEnvironmentFlags = { has: jest.fn(() => true) } as any const configPath = 'webpack.config.js' - const task = new ProductionWebpack(logger, { configPath }) + const task = new ProductionWebpack(logger, 'ProductionWebpack', { configPath }) await task.run() expect(mockedFork.mock.calls[0][2]?.execArgv).toEqual( @@ -70,7 +70,7 @@ describe('webpack', () => { process.allowedNodeEnvironmentFlags = { has: jest.fn(() => false) } as any const configPath = 'webpack.config.js' - const task = new ProductionWebpack(logger, { configPath }) + const task = new ProductionWebpack(logger, 'ProductionWebpack', { configPath }) await task.run() expect(mockedFork.mock.calls[0][2]?.execArgv).toEqual( From ae2f1d506e49f019d612d7aaae9d8842e6df7a9f Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 9 Nov 2023 17:06:39 +0000 Subject: [PATCH 010/321] test: remove tests for things that have been refactored --- core/cli/test/files/invalid/.gitignore | 1 - core/cli/test/files/invalid/.toolkitrc.yml | 2 -- .../files/invalid/node_modules/invalid/index.js | 4 ---- .../invalid/node_modules/invalid/package.json | 6 ------ core/cli/test/index.test.ts | 17 +---------------- 5 files changed, 1 insertion(+), 29 deletions(-) delete mode 100644 core/cli/test/files/invalid/.gitignore delete mode 100644 core/cli/test/files/invalid/.toolkitrc.yml delete mode 100644 core/cli/test/files/invalid/node_modules/invalid/index.js delete mode 100644 core/cli/test/files/invalid/node_modules/invalid/package.json diff --git a/core/cli/test/files/invalid/.gitignore b/core/cli/test/files/invalid/.gitignore deleted file mode 100644 index cf4bab9dd..000000000 --- a/core/cli/test/files/invalid/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!node_modules diff --git a/core/cli/test/files/invalid/.toolkitrc.yml b/core/cli/test/files/invalid/.toolkitrc.yml deleted file mode 100644 index 3438468d8..000000000 --- a/core/cli/test/files/invalid/.toolkitrc.yml +++ /dev/null @@ -1,2 +0,0 @@ -plugins: - - invalid diff --git a/core/cli/test/files/invalid/node_modules/invalid/index.js b/core/cli/test/files/invalid/node_modules/invalid/index.js deleted file mode 100644 index 3e0126f4f..000000000 --- a/core/cli/test/files/invalid/node_modules/invalid/index.js +++ /dev/null @@ -1,4 +0,0 @@ -class InvalidTask {} - -exports.tasks = [InvalidTask] -exports.hooks = [] diff --git a/core/cli/test/files/invalid/node_modules/invalid/package.json b/core/cli/test/files/invalid/node_modules/invalid/package.json deleted file mode 100644 index 1bcc6ba1c..000000000 --- a/core/cli/test/files/invalid/node_modules/invalid/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "invalid", - "version": "0.0.0", - "main": "index.js", - "license": "ISC" -} diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index c91ec5638..376a1a0b9 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -1,5 +1,5 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -import { Invalid, Plugin, Valid } from '@dotcom-tool-kit/types' +import { Plugin, Valid } from '@dotcom-tool-kit/types' import { describe, expect, it, jest } from '@jest/globals' import * as path from 'path' import winston, { Logger } from 'winston' @@ -12,20 +12,6 @@ const logger = (winston as unknown) as Logger jest.setTimeout(20000) describe('cli', () => { - it('should report when plugins are invalid', async () => { - const config = createConfig() - - const plugin = await loadPlugin('app root', config, logger, { - id: 'invalid plugin test root', - root: path.join(__dirname, 'files/invalid') - }) - - expect(plugin.valid).toBe(false) - const reason = (plugin as Invalid).reasons[0] - expect(reason).toContain('type symbol is missing') - expect(reason).toContain('plugin is not an object') - }) - it('should indicate when there are conflicts', async () => { const config = createConfig() @@ -86,7 +72,6 @@ describe('cli', () => { try { const validConfig = validateConfig(validPluginConfig, logger) expect(validConfig).not.toHaveProperty('hooks.build:local.conflicting') - expect(validConfig.hooks['build:local'].plugin?.id).toEqual('@dotcom-tool-kit/npm') } catch (e) { if (e instanceof ToolKitError) { e.message += '\n' + e.details From 7f91da377c4f8061dfe9f9c784e2ec75287d9f8e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 14 Nov 2023 12:09:42 +0000 Subject: [PATCH 011/321] refactor: split validated out of types index --- lib/types/src/index.ts | 81 +------------------------------------- lib/types/src/validated.ts | 80 +++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 79 deletions(-) create mode 100644 lib/types/src/validated.ts diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 55f13d9b8..3a24ccae4 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -1,10 +1,10 @@ -import { ToolKitError } from '@dotcom-tool-kit/error' import { styles as s } from '@dotcom-tool-kit/logger' import fs from 'fs' import path from 'path' import semver from 'semver' import type { Logger } from 'winston' import { z } from 'zod' +import { Validated } from './validated' const packageJsonPath = path.resolve(__dirname, '../package.json') const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) @@ -21,84 +21,7 @@ const baseSymbol = Symbol.for('@dotcom-tool-kit/types/base') const taskSymbol = Symbol.for('@dotcom-tool-kit/types/task') const hookSymbol = Symbol.for('@dotcom-tool-kit/types/hook') -export interface Invalid { - valid: false - reasons: string[] -} -export interface Valid { - valid: true - value: T -} -export type Validated = Invalid | Valid - -export function mapValidated(validated: Validated, f: (val: T) => U): Validated { - if (validated.valid) { - return { valid: true, value: f(validated.value) } - } else { - return validated - } -} - -export function mapValidationError( - validated: Validated, - f: (reasons: string[]) => string[] -): Validated { - if (validated.valid) { - return validated - } else { - return { valid: false, reasons: f(validated.reasons) } - } -} - -export function joinValidated(first: Validated, second: Validated): Validated<[T, U]> { - if (first.valid) { - if (second.valid) { - return { valid: true, value: [first.value, second.value] } - } else { - return second - } - } else { - if (second.valid) { - return first - } else { - return { valid: false, reasons: [...first.reasons, ...second.reasons] } - } - } -} - -export function reduceValidated(validated: Validated[]): Validated { - let sequenced: Validated = { valid: true, value: [] } - for (const val of validated) { - if (sequenced.valid) { - if (val.valid) { - sequenced.value.push(val.value) - } else { - sequenced = { valid: false, reasons: val.reasons } - } - } else if (!val.valid) { - sequenced.reasons.push(...val.reasons) - } - } - return sequenced -} - -export function flatMapValidated(validated: Validated, f: (val: T) => Validated): Validated { - if (validated.valid) { - return f(validated.value) - } else { - return validated - } -} - -export function unwrapValidated(validated: Validated, message = ''): T { - if (validated.valid) { - return validated.value - } else { - const error = new ToolKitError(message) - error.details = validated.reasons.join('\n\n') - throw error - } -} +export * from './validated' abstract class Base { static version = version diff --git a/lib/types/src/validated.ts b/lib/types/src/validated.ts new file mode 100644 index 000000000..e563e0e1b --- /dev/null +++ b/lib/types/src/validated.ts @@ -0,0 +1,80 @@ +import { ToolKitError } from '@dotcom-tool-kit/error' + +export interface Invalid { + valid: false + reasons: string[] +} +export interface Valid { + valid: true + value: T +} +export type Validated = Invalid | Valid + +export function mapValidated(validated: Validated, f: (val: T) => U): Validated { + if (validated.valid) { + return { valid: true, value: f(validated.value) } + } else { + return validated + } +} + +export function mapValidationError( + validated: Validated, + f: (reasons: string[]) => string[] +): Validated { + if (validated.valid) { + return validated + } else { + return { valid: false, reasons: f(validated.reasons) } + } +} + +export function joinValidated(first: Validated, second: Validated): Validated<[T, U]> { + if (first.valid) { + if (second.valid) { + return { valid: true, value: [first.value, second.value] } + } else { + return second + } + } else { + if (second.valid) { + return first + } else { + return { valid: false, reasons: [...first.reasons, ...second.reasons] } + } + } +} + +export function reduceValidated(validated: Validated[]): Validated { + let sequenced: Validated = { valid: true, value: [] } + for (const val of validated) { + if (sequenced.valid) { + if (val.valid) { + sequenced.value.push(val.value) + } else { + sequenced = { valid: false, reasons: val.reasons } + } + } else if (!val.valid) { + sequenced.reasons.push(...val.reasons) + } + } + return sequenced +} + +export function flatMapValidated(validated: Validated, f: (val: T) => Validated): Validated { + if (validated.valid) { + return f(validated.value) + } else { + return validated + } +} + +export function unwrapValidated(validated: Validated, message = ''): T { + if (validated.valid) { + return validated.value + } else { + const error = new ToolKitError(message) + error.details = validated.reasons.join('\n\n') + throw error + } +} From f28176db655d0265ccf4d9568a761dd572277f64 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 14 Nov 2023 12:37:35 +0000 Subject: [PATCH 012/321] refactor: split base, hook and task into their own files --- lib/types/src/base.ts | 64 +++++++++++++++++ lib/types/src/hook.ts | 41 +++++++++++ lib/types/src/index.ts | 148 ++------------------------------------- lib/types/src/symbols.ts | 10 +++ lib/types/src/task.ts | 36 ++++++++++ 5 files changed, 155 insertions(+), 144 deletions(-) create mode 100644 lib/types/src/base.ts create mode 100644 lib/types/src/hook.ts create mode 100644 lib/types/src/symbols.ts create mode 100644 lib/types/src/task.ts diff --git a/lib/types/src/base.ts b/lib/types/src/base.ts new file mode 100644 index 000000000..ef73f5ec2 --- /dev/null +++ b/lib/types/src/base.ts @@ -0,0 +1,64 @@ +import { styles as s } from '@dotcom-tool-kit/logger' +import path from 'path' +import fs from 'fs' +import { baseSymbol, typeSymbol } from './symbols' +import { Validated } from './validated' +import semver from 'semver' + +const packageJsonPath = path.resolve(__dirname, '../package.json') +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) +const version: string = packageJson.version + +export abstract class Base { + static version = version + version = version + + static get [typeSymbol](): symbol { + return baseSymbol + } + + get [typeSymbol](): symbol { + return baseSymbol + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + static is(objectToCheck: any): objectToCheck is T { + return objectToCheck[typeSymbol] === this[typeSymbol] + } + + static isCompatible(objectToCheck: unknown): Validated { + if (!this.is(objectToCheck)) { + return { + valid: false, + reasons: [ + `${s.plugin( + '@dotcom-tool-kit/types' + )} type symbol is missing, make sure that this object derives from the ${s.code( + 'Task' + )} or ${s.code('Hook')} class defined by the plugin` + ] + } + } + + // an 'objectToCheck' from a plugin is compatible with this CLI if its + // version is semver-compatible with the @dotcom-tool-kit/types included by + // the CLI (which is what's calling this). so, prepend ^ to our version, + // and check our version satisfies that. + + // this lets e.g. a CLI that includes types@2.2.0 load any plugin + // that depends on any higher minor version of types. + const range = `^${this.version}` + if (semver.satisfies(objectToCheck.version, range)) { + return { valid: true, value: objectToCheck as T } + } else { + return { + valid: false, + reasons: [ + `object is from an outdated version of ${s.plugin( + '@dotcom-tool-kit/types' + )}, make sure you're using at least version ${s.heading(this.version)} of the plugin` + ] + } + } + } +} diff --git a/lib/types/src/hook.ts b/lib/types/src/hook.ts new file mode 100644 index 000000000..694e6a83d --- /dev/null +++ b/lib/types/src/hook.ts @@ -0,0 +1,41 @@ +import type { Logger } from 'winston' +import { Base } from './base' +import { hookSymbol, typeSymbol } from './symbols' + +export abstract class Hook extends Base { + logger: Logger + static description?: string + id: string + // This field is used to collect hooks that share state when running their + // install methods. All hooks in the same group will run their install method + // one after the other, and then their commitInstall method will be run with + // the collected state. + installGroup?: string + + static get [typeSymbol](): symbol { + return hookSymbol + } + + get [typeSymbol](): symbol { + return hookSymbol + } + + constructor(logger: Logger, id: string) { + super() + + this.id = id + this.logger = logger.child({ hook: this.constructor.name }) + } + + abstract check(): Promise + abstract install(state?: State): Promise + // Intentional unused parameter as pre-fixed with an underscore + // eslint-disable-next-line no-unused-vars + async commitInstall(_state: State): Promise { + return + } +} + +export type HookConstructor = { new (logger: Logger, id: string): Hook } + +export type HookClass = HookConstructor & typeof Hook diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 3a24ccae4..b0802f9ef 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -1,149 +1,9 @@ -import { styles as s } from '@dotcom-tool-kit/logger' -import fs from 'fs' -import path from 'path' -import semver from 'semver' -import type { Logger } from 'winston' -import { z } from 'zod' -import { Validated } from './validated' - -const packageJsonPath = path.resolve(__dirname, '../package.json') -const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) -const version: string = packageJson.version - -// uses Symbol.for, not Symbol, so that they're compatible across different -// @dotcom-tool-kit/types instances - -// used as the name for the property we use to identify classes -const typeSymbol = Symbol.for('@dotcom-tool-kit/types') - -// used to identify the Base, Task and Hook classes -const baseSymbol = Symbol.for('@dotcom-tool-kit/types/base') -const taskSymbol = Symbol.for('@dotcom-tool-kit/types/task') -const hookSymbol = Symbol.for('@dotcom-tool-kit/types/hook') +import type { HookConstructor } from './hook' +import type { TaskConstructor } from './task' export * from './validated' - -abstract class Base { - static version = version - version = version - - static get [typeSymbol](): symbol { - return baseSymbol - } - - get [typeSymbol](): symbol { - return baseSymbol - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - static is(objectToCheck: any): objectToCheck is T { - return objectToCheck[typeSymbol] === this[typeSymbol] - } - - static isCompatible(objectToCheck: unknown): Validated { - if (!this.is(objectToCheck)) { - return { - valid: false, - reasons: [ - `${s.plugin( - '@dotcom-tool-kit/types' - )} type symbol is missing, make sure that this object derives from the ${s.code( - 'Task' - )} or ${s.code('Hook')} class defined by the plugin` - ] - } - } - - // an 'objectToCheck' from a plugin is compatible with this CLI if its - // version is semver-compatible with the @dotcom-tool-kit/types included by - // the CLI (which is what's calling this). so, prepend ^ to our version, - // and check our version satisfies that. - - // this lets e.g. a CLI that includes types@2.2.0 load any plugin - // that depends on any higher minor version of types. - const range = `^${this.version}` - if (semver.satisfies(objectToCheck.version, range)) { - return { valid: true, value: objectToCheck as T } - } else { - return { - valid: false, - reasons: [ - `object is from an outdated version of ${s.plugin( - '@dotcom-tool-kit/types' - )}, make sure you're using at least version ${s.heading(this.version)} of the plugin` - ] - } - } - } -} - -export abstract class Task extends Base { - static description: string - id: string - - static get [typeSymbol](): symbol { - return taskSymbol - } - - get [typeSymbol](): symbol { - return taskSymbol - } - - options: z.output - logger: Logger - - constructor(logger: Logger, id: string, options: z.output) { - super() - - this.id = id - this.options = options - this.logger = logger.child({ task: id }) - } - - abstract run(files?: string[]): Promise -} - -export type TaskConstructor = { - new (logger: Logger, id: string, options: Partial>): Task -} - -export type TaskClass = TaskConstructor & typeof Task - -export abstract class Hook extends Base { - logger: Logger - static description?: string - id: string - // This field is used to collect hooks that share state when running their - // install methods. All hooks in the same group will run their install method - // one after the other, and then their commitInstall method will be run with - // the collected state. - installGroup?: string - - static get [typeSymbol](): symbol { - return hookSymbol - } - - get [typeSymbol](): symbol { - return hookSymbol - } - - constructor(logger: Logger, id: string) { - super() - - this.id = id - this.logger = logger.child({ hook: this.constructor.name }) - } - - abstract check(): Promise - abstract install(state?: State): Promise - // Intentional unused parameter as pre-fixed with an underscore - // eslint-disable-next-line no-unused-vars - async commitInstall(_state: State): Promise { - return - } -} - -export type HookConstructor = { new (logger: Logger, id: string): Hook } +export * from './task' +export * from './hook' export type RCFile = { plugins: string[] diff --git a/lib/types/src/symbols.ts b/lib/types/src/symbols.ts new file mode 100644 index 000000000..63cc91965 --- /dev/null +++ b/lib/types/src/symbols.ts @@ -0,0 +1,10 @@ +// uses Symbol.for, not Symbol, so that they're compatible across different +// @dotcom-tool-kit/types instances + +// used as the name for the property we use to identify classes +export const typeSymbol = Symbol.for('@dotcom-tool-kit/types') + +// used to identify the Base, Task and Hook classes +export const baseSymbol = Symbol.for('@dotcom-tool-kit/types/base') +export const taskSymbol = Symbol.for('@dotcom-tool-kit/types/task') +export const hookSymbol = Symbol.for('@dotcom-tool-kit/types/hook') diff --git a/lib/types/src/task.ts b/lib/types/src/task.ts new file mode 100644 index 000000000..f08fb3b43 --- /dev/null +++ b/lib/types/src/task.ts @@ -0,0 +1,36 @@ +import { z } from 'zod' +import { Base } from './base' +import { taskSymbol, typeSymbol } from './symbols' +import type { Logger } from 'winston' + +export abstract class Task extends Base { + static description: string + id: string + + static get [typeSymbol](): symbol { + return taskSymbol + } + + get [typeSymbol](): symbol { + return taskSymbol + } + + options: z.output + logger: Logger + + constructor(logger: Logger, id: string, options: z.output) { + super() + + this.id = id + this.options = options + this.logger = logger.child({ task: id }) + } + + abstract run(files?: string[]): Promise +} + +export type TaskConstructor = { + new (logger: Logger, id: string, options: Partial>): Task +} + +export type TaskClass = TaskConstructor & typeof Task From 074a691fcca53b40d38613fc70cbcfb709ed394d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 14 Nov 2023 16:01:47 +0000 Subject: [PATCH 013/321] fix: only load the tasks that are needed for the hooks that are running --- core/cli/src/index.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index a8c74a27f..51c218fb0 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -36,18 +36,23 @@ export const shouldDisableNativeFetch = (): boolean => { ) } -const loadTasks = async (logger: Logger, config: ValidConfig): Promise>> => +const loadTasks = async ( + logger: Logger, + taskNames: string[], + config: ValidConfig +): Promise>> => mapValidated( reduceValidated( await Promise.all( - Object.entries(config.tasks).map(async ([taskName, pluginId]) => - flatMapValidated(await importPlugin(pluginId), (plugin) => + taskNames.map(async (taskName) => { + const pluginId = config.tasks[taskName] + return flatMapValidated(await importPlugin(pluginId), (plugin) => mapValidated(validatePluginTasks(plugin as RawPluginModule), (tasks) => [ taskName, new tasks[taskName](logger, taskName, getOptions(pluginId as OptionKey) ?? {}) ]) ) - ) + }) ) ), Object.fromEntries From 78fcd226c749b3f9828a3987f69faf66db37bb08 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 14 Nov 2023 16:09:09 +0000 Subject: [PATCH 014/321] refactor: reduce nesting in loadHooks and loadTasks --- core/cli/src/config.ts | 26 ++++++++++++++------------ core/cli/src/index.ts | 37 ++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 6a6ccd8de..5eab4775a 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -69,20 +69,22 @@ export type ValidConfig = Omit[]>> => - reduceValidated( - await Promise.all( - Object.entries(config.hooks).map(async ([hookName, pluginId]) => - flatMapValidated(await importPlugin(pluginId), (plugin) => - mapValidated( - validatePluginHooks(plugin as RawPluginModule), - (hooks) => new hooks[hookName](logger, hookName) - ) - ) - ) - ) +export const loadHooks = async (logger: Logger, config: ValidConfig): Promise[]>> => { + const hookResults = await Promise.all( + Object.entries(config.hooks).map(async ([hookName, pluginId]) => { + const hookPlugin = await importPlugin(pluginId) + + return flatMapValidated(hookPlugin, (plugin) => { + const pluginHooks = validatePluginHooks(plugin as RawPluginModule) + + return mapValidated(pluginHooks, (hooks) => new hooks[hookName](logger, hookName)) + }) + }) ) + return reduceValidated(hookResults) +} + export async function fileHash(path: string): Promise { const hashFunc = createHash('sha512') try { diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 51c218fb0..dfd083ccf 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -40,24 +40,26 @@ const loadTasks = async ( logger: Logger, taskNames: string[], config: ValidConfig -): Promise>> => - mapValidated( - reduceValidated( - await Promise.all( - taskNames.map(async (taskName) => { - const pluginId = config.tasks[taskName] - return flatMapValidated(await importPlugin(pluginId), (plugin) => - mapValidated(validatePluginTasks(plugin as RawPluginModule), (tasks) => [ - taskName, - new tasks[taskName](logger, taskName, getOptions(pluginId as OptionKey) ?? {}) - ]) - ) - }) - ) - ), - Object.fromEntries +): Promise>> => { + const taskResults = await Promise.all( + taskNames.map(async (taskName) => { + const pluginId = config.tasks[taskName] + const taskPlugin = await importPlugin(pluginId) + + return flatMapValidated(taskPlugin, (plugin) => { + const pluginTasks = validatePluginTasks(plugin as RawPluginModule) + + return mapValidated(pluginTasks, (tasks) => [ + taskName, + new tasks[taskName](logger, taskName, getOptions(pluginId as OptionKey) ?? {}) + ]) + }) + }) ) + return mapValidated(reduceValidated(taskResults), Object.fromEntries) +} + export async function runTasks(logger: Logger, hooks: string[], files?: string[]): Promise { const config = await loadConfig(logger) @@ -89,7 +91,8 @@ ${availableHooks}` process.execArgv.push('--no-experimental-fetch') } - const tasks = unwrapValidated(await loadTasks(logger, config), 'tasks are invalid') + const taskNames = hooks.flatMap((hook) => config.hookTasks[hook]?.tasks ?? []) + const tasks = unwrapValidated(await loadTasks(logger, taskNames, config), 'tasks are invalid') for (const hook of hooks) { const errors: ErrorSummary[] = [] From 28b0e890994bb267c878da0109a14a16fc7fbdc5 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 14 Nov 2023 13:09:12 +0000 Subject: [PATCH 015/321] fix: fix error message for conflicting tasks and hooks --- core/cli/src/config.ts | 6 +++--- core/cli/src/conflict.ts | 6 ++++++ core/cli/src/messages.ts | 20 ++++++++++---------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 5eab4775a..22e3cc309 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -6,7 +6,7 @@ import type { Logger } from 'winston' import type { HookTask } from './hook' import { RawPluginModule, importPlugin, loadPlugin, resolvePlugin, validatePluginHooks } from './plugin' -import { Conflict, findConflicts, withoutConflicts, isConflict } from './conflict' +import { Conflict, findConflicts, withoutConflicts, isConflict, findConflictingEntries } from './conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' import { @@ -161,8 +161,8 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali const validConfig = config as ValidConfig const hookTaskConflicts = findConflicts(Object.values(config.hookTasks)) - const hookConflicts = findConflicts(Object.values(config.hooks)) - const taskConflicts = findConflicts(Object.values(config.tasks)) + const hookConflicts = findConflictingEntries(config.hooks) + const taskConflicts = findConflictingEntries(config.tasks) const optionConflicts = findConflicts(Object.values(config.options)) const definedHookTaskConflicts = hookTaskConflicts.filter((conflict) => { diff --git a/core/cli/src/conflict.ts b/core/cli/src/conflict.ts index ccdac3d20..9fee842de 100644 --- a/core/cli/src/conflict.ts +++ b/core/cli/src/conflict.ts @@ -9,6 +9,12 @@ export function isConflict(thing: unknown): thing is Conflict { return Boolean((thing as Conflict).conflicting) } +export function findConflictingEntries( + items: Record> +): [string, Conflict][] { + return Object.entries(items).filter((entry): entry is [string, Conflict] => isConflict(entry[1])) +} + export function findConflicts(items: (U | Conflict)[]): Conflict[] { const conflicts: Conflict[] = [] diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index b520cafb6..454cfbf36 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -6,24 +6,24 @@ import type { PluginOptions } from './config' import type { Conflict } from './conflict' import type { HookTask } from './hook' -const formatTaskConflict = (conflict: Conflict): string => - `- ${s.task(conflict.conflicting[0] ?? 'unknown task')} ${s.dim( - 'from plugins' - )} ${conflict.conflicting.map((task) => s.plugin(task ?? 'unknown plugin')).join(s.dim(', '))}` +const formatTaskConflict = ([key, conflict]: [string, Conflict]): string => + `- ${s.task(key ?? 'unknown task')} ${s.dim('from plugins')} ${conflict.conflicting + .map((task) => s.plugin(task ?? 'unknown plugin')) + .join(s.dim(', '))}` -export const formatTaskConflicts = (conflicts: Conflict[]): string => `${s.heading( +export const formatTaskConflicts = (conflicts: [string, Conflict][]): string => `${s.heading( 'There are multiple plugins that include the same tasks' )}: ${conflicts.map(formatTaskConflict).join('\n')} You must resolve this conflict by removing all but one of these plugins.` -const formatHookConflict = (conflict: Conflict): string => - `- ${s.hook(conflict.conflicting[0] ?? 'unknown event')} ${s.dim( - 'from plugins' - )} ${conflict.conflicting.map((task) => s.plugin(task ?? 'unknown plugin')).join(s.dim(', '))}` +const formatHookConflict = ([key, conflict]: [string, Conflict]): string => + `- ${s.hook(key ?? 'unknown hook')} ${s.dim('from plugins')} ${conflict.conflicting + .map((task) => s.plugin(task ?? 'unknown plugin')) + .join(s.dim(', '))}` -export const formatHookConflicts = (conflicts: Conflict[]): string => `${s.heading( +export const formatHookConflicts = (conflicts: [string, Conflict][]): string => `${s.heading( 'There are multiple plugins that include the same hooks' )}: ${conflicts.map(formatHookConflict).join('\n')} From 2316ee2a468d2277834296afbf90701270b82ccb Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 2 Nov 2023 11:47:14 +0000 Subject: [PATCH 016/321] chore: fix configuration for no-unused-vars to correctly allow underscore-prefixed vars --- .eslintrc.js | 2 ++ lib/types/src/hook.ts | 2 -- plugins/heroku/test/setConfigVars.test.ts | 3 --- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 8b3f39c2a..01b037ab4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,6 +11,8 @@ module.exports = { rules: { // We use winston's logging instead 'no-console': 'error', + // conflicts with @typescript-eslint/no-unused-vars + 'no-unused-vars': 'off', // Necessary to allow us to define arguments in a method that only subclasses use // https://github.com/typescript-eslint/typescript-eslint/issues/586#issuecomment-510099609 '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }] diff --git a/lib/types/src/hook.ts b/lib/types/src/hook.ts index 694e6a83d..fe5245755 100644 --- a/lib/types/src/hook.ts +++ b/lib/types/src/hook.ts @@ -29,8 +29,6 @@ export abstract class Hook extends Base { abstract check(): Promise abstract install(state?: State): Promise - // Intentional unused parameter as pre-fixed with an underscore - // eslint-disable-next-line no-unused-vars async commitInstall(_state: State): Promise { return } diff --git a/plugins/heroku/test/setConfigVars.test.ts b/plugins/heroku/test/setConfigVars.test.ts index 1287cb4e6..d5b708d97 100644 --- a/plugins/heroku/test/setConfigVars.test.ts +++ b/plugins/heroku/test/setConfigVars.test.ts @@ -4,7 +4,6 @@ import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import heroku from '../src/herokuClient' import winston, { Logger } from 'winston' const logger = (winston as unknown) as Logger -/* eslint-disable @typescript-eslint/no-unused-vars */ type DopplerPath = { project: string } @@ -38,8 +37,6 @@ const reviewPatchBody = { } class DopplerEnvVarsMock { dopplerPath: DopplerPath - // Intentional unused parameter as pre-fixed with an underscore - // eslint-disable-next-line no-unused-vars constructor(_dopplerPath: DopplerPath, public environment: string, private migrated: boolean) { this.dopplerPath = dopplerPath } From 84f26a54eca7465e7ddebf4315858805bffa1938 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 13 Oct 2023 16:46:27 +0100 Subject: [PATCH 017/321] chore!: remove legacy circleci postinstall backwards compatibility --- core/cli/src/install.ts | 9 ------- core/cli/src/postInstall.ts | 53 ------------------------------------- 2 files changed, 62 deletions(-) delete mode 100644 core/cli/src/postInstall.ts diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index b0dee9e6f..12ee154d6 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -3,7 +3,6 @@ import { OptionKey, setOptions } from '@dotcom-tool-kit/options' import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' import { loadConfig, loadHooks, updateHashes, ValidConfig } from './config' -import { postInstall } from './postInstall' import { unwrapValidated } from '@dotcom-tool-kit/types' // implementation of the Array.every method that supports asynchronous predicates @@ -60,14 +59,6 @@ export default async function installHooks(logger: Logger): Promise } } - // HACK: achieve backwards compatibility with older versions of the circleci - // plugin that required a postinstall function to run instead of the new - // commitInstall method. remove in major update of cli. - const usesNewCircleCIGroup = Object.keys(groups).includes('circleci') - if (!usesNewCircleCIGroup) { - await postInstall(logger) - } - if (errors.length) { const error = new ToolKitError('could not automatically install hooks:') error.details = errors.map((error) => `- ${error.message}`).join('\n') diff --git a/core/cli/src/postInstall.ts b/core/cli/src/postInstall.ts deleted file mode 100644 index 8777647d6..000000000 --- a/core/cli/src/postInstall.ts +++ /dev/null @@ -1,53 +0,0 @@ -import path from 'path' -import { promises as fs } from 'fs' -import { semVerRegex } from '@dotcom-tool-kit/types/lib/npm' -import * as YAML from 'yaml' -import { Pair, YAMLMap, YAMLSeq } from 'yaml/types' -import merge from 'lodash/merge' -import type { Logger } from 'winston' -import { automatedComment, JobConfig } from '@dotcom-tool-kit/types/lib/circleci' - -/** - * This step adds the tags only filter to rest of the jobs in the workflow if there is a job that contains the semverRegex. - * CircleCI will only run the jobs if the rest of the jobs have the tags filter. - */ -export async function postInstall(logger: Logger): Promise { - const circleConfigPath = path.resolve(process.cwd(), '.circleci/config.yml') - try { - const rawCircleConfig = await fs.readFile(circleConfigPath, 'utf8') - if ( - rawCircleConfig && - rawCircleConfig.includes(semVerRegex.source) && - rawCircleConfig.startsWith(automatedComment) - ) { - logger.verbose('running postInstall step') - const yml = YAML.parseDocument(rawCircleConfig) - const workflows: YAMLMap = yml.get('workflows') - const toolkitWorkflow = workflows.get('tool-kit') - const jobs: YAMLSeq = toolkitWorkflow.get('jobs') - jobs?.items.forEach((jobItem, index) => { - const tagsFilterConfig: JobConfig = { filters: { tags: { only: `${semVerRegex}` } } } - if (jobItem.type === 'PLAIN') { - // eg. - checkout - const node = YAML.createNode({ [jobItem.value]: tagsFilterConfig }) - jobs.items[index] = node - } else { - const job: Pair = (jobItem as YAMLMap).items[0] - const existingFilter: Pair | undefined = job.value.items.filter( - (item: Pair) => item.key.value === 'filters' - )[0] - const merged = existingFilter ? merge(existingFilter.toJSON(), tagsFilterConfig) : tagsFilterConfig - const node = YAML.createNode(merged['filters']) - job.value.set('filters', node) - } - }) - logger.info(`writing postInstall results to file ${circleConfigPath}`) - await fs.writeFile(circleConfigPath, yml.toString()) - } - } catch (error) { - // Not an error if config file doesn't exist - if ((error as NodeJS.ErrnoException).code !== 'ENOENT') { - throw error - } - } -} From 91daa0e13ebe5440fbdd5783c2b7eead5f588a22 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 10 Oct 2023 15:54:26 +0100 Subject: [PATCH 018/321] feat!: rename `hooks` in toolkitrc to `commands` --- core/cli/src/plugin.ts | 2 +- core/cli/src/rc-file.ts | 4 ++-- core/cli/test/files/conflict-resolution/.toolkitrc.yml | 2 +- core/cli/test/files/conflicted/.toolkitrc.yml | 2 +- core/cli/test/files/cousins/.toolkitrc.yml | 2 +- core/cli/test/files/duplicate/.toolkitrc.yml | 2 +- core/cli/test/files/successful/.toolkitrc.yml | 2 +- core/create/src/index.ts | 2 +- core/create/src/prompts/conflicts.ts | 2 +- lib/types/src/index.ts | 2 +- plugins/babel/.toolkitrc.yml | 2 +- plugins/backend-heroku-app/.toolkitrc.yml | 2 +- plugins/backend-serverless-app/.toolkitrc.yml | 2 +- plugins/circleci-heroku/.toolkitrc.yml | 2 +- plugins/circleci-npm/.toolkitrc.yml | 2 +- plugins/cypress/.toolkitrc.yml | 3 +-- plugins/eslint/.toolkitrc.yml | 2 +- plugins/frontend-app/.toolkitrc.yml | 2 +- plugins/heroku/.toolkitrc.yml | 2 +- plugins/jest/.toolkitrc.yml | 2 +- plugins/lint-staged/.toolkitrc.yml | 2 +- plugins/mocha/.toolkitrc.yml | 2 +- plugins/n-test/.toolkitrc.yml | 2 +- plugins/next-router/.toolkitrc.yml | 2 +- plugins/node/.toolkitrc.yml | 2 +- plugins/nodemon/.toolkitrc.yml | 2 +- plugins/pa11y/.toolkitrc.yml | 2 +- plugins/prettier/.toolkitrc.yml | 4 ++-- plugins/typescript/.toolkitrc.yml | 2 +- plugins/upload-assets-to-s3/.toolkitrc.yml | 2 +- plugins/webpack/.toolkitrc.yml | 2 +- 31 files changed, 33 insertions(+), 34 deletions(-) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index ec1dc6d17..ad3435406 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -215,7 +215,7 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger // load plugin hook tasks. do this after loading child plugins, so // parent hooks get assigned after child hooks and can override them - for (const [id, configHookTask] of Object.entries(plugin.rcFile.hooks)) { + for (const [id, configHookTask] of Object.entries(plugin.rcFile.commands)) { // handle conflicts between hooks from different plugins const existingHookTask = config.hookTasks[id] const newHookTask: HookTask = { diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index cd531cbba..202f2fdd4 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -5,7 +5,7 @@ import * as path from 'path' import type { Logger } from 'winston' export const explorer = cosmiconfig('toolkit', { ignoreEmptySearchPlaces: false }) -const emptyConfig = { plugins: [], installs: [], tasks: [], hooks: {}, options: {} } +const emptyConfig = { plugins: [], installs: [], tasks: [], commands: {}, options: {} } let rootConfig: string | undefined type RawRCFile = { @@ -37,7 +37,7 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo plugins: config.plugins ?? [], installs: config.installs ?? [], tasks: config.tasks ?? [], - hooks: config.hooks ?? {}, + commands: config.commands ?? {}, options: config.options ?? {} } } diff --git a/core/cli/test/files/conflict-resolution/.toolkitrc.yml b/core/cli/test/files/conflict-resolution/.toolkitrc.yml index 390ed216c..537d7d76d 100644 --- a/core/cli/test/files/conflict-resolution/.toolkitrc.yml +++ b/core/cli/test/files/conflict-resolution/.toolkitrc.yml @@ -17,7 +17,7 @@ options: team: platforms app: tool-kit-test -hooks: +commands: build:local: - WebpackDevelopment - BabelDevelopment diff --git a/core/cli/test/files/conflicted/.toolkitrc.yml b/core/cli/test/files/conflicted/.toolkitrc.yml index b5aba1588..273807168 100644 --- a/core/cli/test/files/conflicted/.toolkitrc.yml +++ b/core/cli/test/files/conflicted/.toolkitrc.yml @@ -6,4 +6,4 @@ plugins: options: -hooks: +commands: diff --git a/core/cli/test/files/cousins/.toolkitrc.yml b/core/cli/test/files/cousins/.toolkitrc.yml index 7555dd964..88834875f 100644 --- a/core/cli/test/files/cousins/.toolkitrc.yml +++ b/core/cli/test/files/cousins/.toolkitrc.yml @@ -6,4 +6,4 @@ plugins: options: -hooks: +commands: diff --git a/core/cli/test/files/duplicate/.toolkitrc.yml b/core/cli/test/files/duplicate/.toolkitrc.yml index 5cbb53077..b0f181d5c 100644 --- a/core/cli/test/files/duplicate/.toolkitrc.yml +++ b/core/cli/test/files/duplicate/.toolkitrc.yml @@ -15,4 +15,4 @@ options: team: platforms app: tool-kit-test -hooks: +commands: diff --git a/core/cli/test/files/successful/.toolkitrc.yml b/core/cli/test/files/successful/.toolkitrc.yml index a9ed03963..0fc808aee 100644 --- a/core/cli/test/files/successful/.toolkitrc.yml +++ b/core/cli/test/files/successful/.toolkitrc.yml @@ -13,7 +13,7 @@ options: '@dotcom-tool-kit/n-test': host: 'https://example.com' -hooks: +commands: 'test:local': - Mocha - Eslint diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 2e44910c5..5739f3db6 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -115,7 +115,7 @@ async function main() { plugins: [], installs: [], tasks: [], - hooks: {}, + commands: {}, options: {} } diff --git a/core/create/src/prompts/conflicts.ts b/core/create/src/prompts/conflicts.ts index f26f3d588..17af1e035 100644 --- a/core/create/src/prompts/conflicts.ts +++ b/core/create/src/prompts/conflicts.ts @@ -62,7 +62,7 @@ Please select the ${ordinal(i)} package to run.`, } } - toolKitConfig.hooks = orderedHooks + toolKitConfig.commands = orderedHooks const configFile = YAML.stringify(toolKitConfig) const { confirm } = await prompt({ diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index b0802f9ef..238adefba 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -9,7 +9,7 @@ export type RCFile = { plugins: string[] installs: string[] tasks: string[] - hooks: { [id: string]: string | string[] } + commands: { [id: string]: string | string[] } options: { [id: string]: Record } } diff --git a/plugins/babel/.toolkitrc.yml b/plugins/babel/.toolkitrc.yml index bedb36ca5..5da99994d 100644 --- a/plugins/babel/.toolkitrc.yml +++ b/plugins/babel/.toolkitrc.yml @@ -2,7 +2,7 @@ tasks: - BabelDevelopment - BabelProduction -hooks: +commands: 'build:local': BabelDevelopment 'build:ci': BabelProduction 'build:remote': BabelProduction diff --git a/plugins/backend-heroku-app/.toolkitrc.yml b/plugins/backend-heroku-app/.toolkitrc.yml index aff1e4846..cc31d2c1c 100644 --- a/plugins/backend-heroku-app/.toolkitrc.yml +++ b/plugins/backend-heroku-app/.toolkitrc.yml @@ -4,7 +4,7 @@ plugins: - '@dotcom-tool-kit/heroku' - '@dotcom-tool-kit/node' -hooks: +commands: 'run:local': Node 'deploy:review': HerokuReview 'deploy:staging': HerokuStaging diff --git a/plugins/backend-serverless-app/.toolkitrc.yml b/plugins/backend-serverless-app/.toolkitrc.yml index 1e100bc76..d5c102f11 100644 --- a/plugins/backend-serverless-app/.toolkitrc.yml +++ b/plugins/backend-serverless-app/.toolkitrc.yml @@ -4,7 +4,7 @@ plugins: - '@dotcom-tool-kit/serverless' - '@dotcom-tool-kit/node' -hooks: +commands: 'run:local': ServerlessRun 'deploy:review': ServerlessProvision 'deploy:production': ServerlessDeploy diff --git a/plugins/circleci-heroku/.toolkitrc.yml b/plugins/circleci-heroku/.toolkitrc.yml index 2eee988b1..480dbe296 100644 --- a/plugins/circleci-heroku/.toolkitrc.yml +++ b/plugins/circleci-heroku/.toolkitrc.yml @@ -2,7 +2,7 @@ plugins: - '@dotcom-tool-kit/circleci-deploy' - '@dotcom-tool-kit/heroku' -hooks: +commands: 'deploy:review': HerokuReview 'deploy:staging': HerokuStaging 'deploy:production': HerokuProduction diff --git a/plugins/circleci-npm/.toolkitrc.yml b/plugins/circleci-npm/.toolkitrc.yml index d40fe44e2..24cdc42df 100644 --- a/plugins/circleci-npm/.toolkitrc.yml +++ b/plugins/circleci-npm/.toolkitrc.yml @@ -5,5 +5,5 @@ plugins: installs: - 'publish:tag' -hooks: +commands: 'publish:tag': NpmPublish diff --git a/plugins/cypress/.toolkitrc.yml b/plugins/cypress/.toolkitrc.yml index 0e879e04c..cc5b99b32 100644 --- a/plugins/cypress/.toolkitrc.yml +++ b/plugins/cypress/.toolkitrc.yml @@ -5,8 +5,7 @@ tasks: - CypressCi - CypressLocal -hooks: +commands: 'test:review': CypressCi 'test:staging': CypressCi 'e2e:local': CypressLocal - diff --git a/plugins/eslint/.toolkitrc.yml b/plugins/eslint/.toolkitrc.yml index 7c45f86a7..4c78bd98c 100644 --- a/plugins/eslint/.toolkitrc.yml +++ b/plugins/eslint/.toolkitrc.yml @@ -1,7 +1,7 @@ tasks: - Eslint -hooks: +commands: 'test:local': Eslint 'test:ci': Eslint 'test:staged': Eslint diff --git a/plugins/frontend-app/.toolkitrc.yml b/plugins/frontend-app/.toolkitrc.yml index d5f03d7e2..f476a469c 100644 --- a/plugins/frontend-app/.toolkitrc.yml +++ b/plugins/frontend-app/.toolkitrc.yml @@ -3,7 +3,7 @@ plugins: - '@dotcom-tool-kit/backend-heroku-app' - '@dotcom-tool-kit/upload-assets-to-s3' -hooks: +commands: 'run:local': - WebpackDevelopment # run a webpack compile before starting the server because dotcom-server-asset-loader expects a manifest to exist - Node diff --git a/plugins/heroku/.toolkitrc.yml b/plugins/heroku/.toolkitrc.yml index 7ed47c0a1..7dcaeaf06 100644 --- a/plugins/heroku/.toolkitrc.yml +++ b/plugins/heroku/.toolkitrc.yml @@ -13,5 +13,5 @@ tasks: - HerokuReview - HerokuTeardown -hooks: +commands: 'cleanup:remote': NpmPrune diff --git a/plugins/jest/.toolkitrc.yml b/plugins/jest/.toolkitrc.yml index 971ef1839..c27583b36 100644 --- a/plugins/jest/.toolkitrc.yml +++ b/plugins/jest/.toolkitrc.yml @@ -2,6 +2,6 @@ tasks: - JestLocal - JestCI -hooks: +commands: 'test:local': JestLocal 'test:ci': JestCI diff --git a/plugins/lint-staged/.toolkitrc.yml b/plugins/lint-staged/.toolkitrc.yml index 58ec908f3..0809c4906 100644 --- a/plugins/lint-staged/.toolkitrc.yml +++ b/plugins/lint-staged/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - LintStaged -hooks: +commands: 'git:precommit': LintStaged diff --git a/plugins/mocha/.toolkitrc.yml b/plugins/mocha/.toolkitrc.yml index 7b7c9b9e9..d08af250b 100644 --- a/plugins/mocha/.toolkitrc.yml +++ b/plugins/mocha/.toolkitrc.yml @@ -1,6 +1,6 @@ tasks: - Mocha -hooks: +commands: 'test:local': Mocha 'test:ci': Mocha diff --git a/plugins/n-test/.toolkitrc.yml b/plugins/n-test/.toolkitrc.yml index 1493160e5..62c144f9b 100644 --- a/plugins/n-test/.toolkitrc.yml +++ b/plugins/n-test/.toolkitrc.yml @@ -1,6 +1,6 @@ tasks: - NTest -hooks: +commands: 'test:review': NTest 'test:staging': NTest diff --git a/plugins/next-router/.toolkitrc.yml b/plugins/next-router/.toolkitrc.yml index 045d3a139..417fca097 100644 --- a/plugins/next-router/.toolkitrc.yml +++ b/plugins/next-router/.toolkitrc.yml @@ -4,6 +4,6 @@ plugins: tasks: - NextRouter -hooks: +commands: run:local: - NextRouter diff --git a/plugins/node/.toolkitrc.yml b/plugins/node/.toolkitrc.yml index 48f385d68..32b662bd2 100644 --- a/plugins/node/.toolkitrc.yml +++ b/plugins/node/.toolkitrc.yml @@ -4,5 +4,5 @@ plugins: tasks: - Node -hooks: +commands: 'run:local': Node diff --git a/plugins/nodemon/.toolkitrc.yml b/plugins/nodemon/.toolkitrc.yml index d59245959..ba8ac1459 100644 --- a/plugins/nodemon/.toolkitrc.yml +++ b/plugins/nodemon/.toolkitrc.yml @@ -4,5 +4,5 @@ plugins: tasks: - Nodemon -hooks: +commands: 'run:local': Nodemon diff --git a/plugins/pa11y/.toolkitrc.yml b/plugins/pa11y/.toolkitrc.yml index b9ff4c523..807c09ef3 100644 --- a/plugins/pa11y/.toolkitrc.yml +++ b/plugins/pa11y/.toolkitrc.yml @@ -4,5 +4,5 @@ plugins: tasks: - Pa11y -hooks: +commands: 'test:local': Pa11y diff --git a/plugins/prettier/.toolkitrc.yml b/plugins/prettier/.toolkitrc.yml index adec8557c..45168b2be 100644 --- a/plugins/prettier/.toolkitrc.yml +++ b/plugins/prettier/.toolkitrc.yml @@ -1,9 +1,9 @@ installs: - - "format:local" + - 'format:local' tasks: - Prettier -hooks: +commands: 'format:local': Prettier 'format:staged': Prettier diff --git a/plugins/typescript/.toolkitrc.yml b/plugins/typescript/.toolkitrc.yml index a09ed8dbf..c824863f3 100644 --- a/plugins/typescript/.toolkitrc.yml +++ b/plugins/typescript/.toolkitrc.yml @@ -3,7 +3,7 @@ tasks: - TypeScriptWatch - TypeScriptTest -hooks: +commands: 'build:local': TypeScriptBuild 'build:ci': TypeScriptBuild 'build:remote': TypeScriptBuild diff --git a/plugins/upload-assets-to-s3/.toolkitrc.yml b/plugins/upload-assets-to-s3/.toolkitrc.yml index 97d28931f..36ad7483a 100644 --- a/plugins/upload-assets-to-s3/.toolkitrc.yml +++ b/plugins/upload-assets-to-s3/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - UploadAssetsToS3 -hooks: +commands: 'release:remote': UploadAssetsToS3 diff --git a/plugins/webpack/.toolkitrc.yml b/plugins/webpack/.toolkitrc.yml index 1a60904ca..4333f40bd 100644 --- a/plugins/webpack/.toolkitrc.yml +++ b/plugins/webpack/.toolkitrc.yml @@ -3,7 +3,7 @@ tasks: - WebpackProduction - WebpackWatch -hooks: +commands: 'build:local': WebpackDevelopment 'build:ci': WebpackProduction 'build:remote': WebpackProduction From bc7c85d6033957e9af224a81186eb8b1798be408 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 10 Oct 2023 16:03:34 +0100 Subject: [PATCH 019/321] refactor: rename hookTasks in config object to commandTasks --- core/cli/src/{hook.ts => command.ts} | 2 +- core/cli/src/config.ts | 49 ++++++++++++++-------------- core/cli/src/help.ts | 2 +- core/cli/src/index.ts | 6 ++-- core/cli/src/messages.ts | 24 +++++++------- core/cli/src/plugin.ts | 46 +++++++++++++------------- core/cli/test/index.test.ts | 19 ++++++----- core/create/src/prompts/conflicts.ts | 6 ++-- lib/error/src/index.ts | 8 ++--- 9 files changed, 84 insertions(+), 78 deletions(-) rename core/cli/src/{hook.ts => command.ts} (77%) diff --git a/core/cli/src/hook.ts b/core/cli/src/command.ts similarity index 77% rename from core/cli/src/hook.ts rename to core/cli/src/command.ts index 733138ec3..ca27c6429 100644 --- a/core/cli/src/hook.ts +++ b/core/cli/src/command.ts @@ -1,6 +1,6 @@ import type { Plugin } from '@dotcom-tool-kit/types' -export interface HookTask { +export interface CommandTask { id: string plugin: Plugin tasks: string[] diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 22e3cc309..3ee4f9049 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -4,7 +4,7 @@ import { readFile } from 'node:fs/promises' import path from 'path' import type { Logger } from 'winston' -import type { HookTask } from './hook' +import type { CommandTask } from './command' import { RawPluginModule, importPlugin, loadPlugin, resolvePlugin, validatePluginHooks } from './plugin' import { Conflict, findConflicts, withoutConflicts, isConflict, findConflictingEntries } from './conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' @@ -22,9 +22,9 @@ import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/sc import { InvalidOption, formatTaskConflicts, - formatUndefinedHookTasks, + formatUndefinedCommandTasks, formatUnusedOptions, - formatHookTaskConflicts, + formatCommandTaskConflicts, formatHookConflicts, formatOptionConflicts, formatUninstalledHooks, @@ -43,7 +43,7 @@ export interface RawConfig { plugins: { [id: string]: Validated } resolvedPlugins: Set tasks: { [id: string]: string | Conflict } - hookTasks: { [id: string]: HookTask | Conflict } + commandTasks: { [id: string]: CommandTask | Conflict } options: { [id: string]: PluginOptions | Conflict | undefined } hooks: { [id: string]: string | Conflict } } @@ -60,9 +60,9 @@ export type ValidOptions = { [Id in keyof SchemaOptions]: ValidPluginOptions } -export type ValidConfig = Omit & { +export type ValidConfig = Omit & { tasks: { [id: string]: string } - hookTasks: { [id: string]: HookTask } + commandTasks: { [id: string]: CommandTask } options: ValidOptions hooks: { [id: string]: string } } @@ -146,7 +146,7 @@ export const createConfig = (): RawConfig => ({ plugins: {}, resolvedPlugins: new Set(), tasks: {}, - hookTasks: {}, + commandTasks: {}, options: {}, hooks: {} }) @@ -160,22 +160,22 @@ async function asyncFilter(items: T[], predicate: (item: T) => Promise { + const definedCommandTaskConflicts = commandTaskConflicts.filter((conflict) => { return conflict.conflicting[0].id in config.hooks }) let shouldThrow = false const error = new ToolKitConflictError( 'There are problems with your Tool Kit configuration.', - hookTaskConflicts.map((conflict) => ({ - hook: conflict.conflicting[0].id, - conflictingTasks: conflict.conflicting.flatMap((hook) => - hook.tasks.map((task) => ({ task, plugin: hook.plugin.id })) + commandTaskConflicts.map((conflict) => ({ + command: conflict.conflicting[0].id, + conflictingTasks: conflict.conflicting.flatMap((command) => + command.tasks.map((task) => ({ task, plugin: command.plugin.id })) ) })) ) @@ -183,7 +183,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali if ( hookConflicts.length > 0 || - definedHookTaskConflicts.length > 0 || + definedCommandTaskConflicts.length > 0 || taskConflicts.length > 0 || optionConflicts.length > 0 ) { @@ -193,8 +193,8 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali error.details += formatHookConflicts(hookConflicts) } - if (definedHookTaskConflicts.length) { - error.details += formatHookTaskConflicts(definedHookTaskConflicts) + if (definedCommandTaskConflicts.length) { + error.details += formatCommandTaskConflicts(definedCommandTaskConflicts) } if (taskConflicts.length) { @@ -206,18 +206,19 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali } } - const configuredHookTasks = withoutConflicts(Object.values(config.hookTasks)) + const configuredCommandTasks = withoutConflicts(Object.values(config.commandTasks)) const definedHookIds = new Set(Object.keys(config.hooks)) - const undefinedHookTasks = configuredHookTasks.filter((hookTask) => { + const undefinedCommandTasks = configuredCommandTasks.filter(() => { + return false //TODO // we only care about undefined hooks that were configured by the app, not default config from plugins - const fromApp = hookTask.plugin.root === process.cwd() - const hookDefined = definedHookIds.has(hookTask.id) - return fromApp && !hookDefined + // const fromApp = commandTask.plugin.root === process.cwd() + // const hookDefined = definedHookIds.has(commandTask.id) + // return fromApp && !hookDefined }) - if (undefinedHookTasks.length > 0) { + if (undefinedCommandTasks.length > 0) { shouldThrow = true - error.details += formatUndefinedHookTasks(undefinedHookTasks, Array.from(definedHookIds)) + error.details += formatUndefinedCommandTasks(undefinedCommandTasks, Array.from(definedHookIds)) } const invalidOptions: InvalidOption[] = [] @@ -270,7 +271,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali error.details += formatUnusedOptions(unusedOptions, Object.keys(config.plugins)) } - const missingTasks = configuredHookTasks + const missingTasks = configuredCommandTasks .map((hook) => ({ hook, tasks: hook.tasks.filter((id) => !config.tasks[id]) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index 5eb563e45..fb2b8981e 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -43,7 +43,7 @@ ${ const Hook = config.hooks[hook] if (Hook) { - const tasks = config.hookTasks[hook] + const tasks = config.commandTasks[hook] /* eslint-disable @typescript-eslint/no-explicit-any -- Object.constructor does not consider static properties */ logger.info(`${styles.heading(hook)} ${(Hook.constructor as any).description ? (Hook.constructor as any).description + '\n' : ''} diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index dfd083ccf..89f583a34 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -91,18 +91,18 @@ ${availableHooks}` process.execArgv.push('--no-experimental-fetch') } - const taskNames = hooks.flatMap((hook) => config.hookTasks[hook]?.tasks ?? []) + const taskNames = hooks.flatMap((hook) => config.commandTasks[hook]?.tasks ?? []) const tasks = unwrapValidated(await loadTasks(logger, taskNames, config), 'tasks are invalid') for (const hook of hooks) { const errors: ErrorSummary[] = [] - if (!config.hookTasks[hook]) { + if (!config.commandTasks[hook]) { logger.warn(`no task configured for ${hook}: skipping assignment...`) continue } - for (const id of config.hookTasks[hook].tasks) { + for (const id of config.commandTasks[hook].tasks) { try { logger.info(styles.taskHeader(`running ${styles.task(id)} task`)) await tasks[id].run(files) diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 454cfbf36..737f5a71d 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -4,7 +4,7 @@ import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' import type { PluginOptions } from './config' import type { Conflict } from './conflict' -import type { HookTask } from './hook' +import type { CommandTask } from './command' const formatTaskConflict = ([key, conflict]: [string, Conflict]): string => `- ${s.task(key ?? 'unknown task')} ${s.dim('from plugins')} ${conflict.conflicting @@ -30,22 +30,22 @@ ${conflicts.map(formatHookConflict).join('\n')} You must resolve this conflict by removing all but one of these plugins.` -const formatHookTaskConflict = (conflict: Conflict): string => `${s.hook( +const formatCommandTaskConflict = (conflict: Conflict): string => `${s.hook( conflict.conflicting[0].id )}: ${conflict.conflicting .map( - (hook) => - `- ${hook.tasks.map(s.task).join(s.dim(', '))} ${s.dim('by plugin')} ${s.plugin(hook.plugin.id)}` + (command) => + `- ${command.tasks.map(s.task).join(s.dim(', '))} ${s.dim('by plugin')} ${s.plugin(command.plugin.id)}` ) .join('\n')} ` -export const formatHookTaskConflicts = (conflicts: Conflict[]): string => `${s.heading( - 'These hooks are configured to run different tasks by multiple plugins' +export const formatCommandTaskConflicts = (conflicts: Conflict[]): string => `${s.heading( + 'These commands are configured to run different tasks by multiple plugins' )}: -${conflicts.map(formatHookTaskConflict).join('\n')} -You must resolve this conflict by explicitly configuring which task to run for these hooks. See ${s.URL( +${conflicts.map(formatCommandTaskConflict).join('\n')} +You must resolve this conflict by explicitly configuring which task to run for these commands. See ${s.URL( 'https://github.com/financial-times/dotcom-tool-kit/tree/main/docs/resolving-hook-conflicts.md' )} for more details. @@ -72,10 +72,10 @@ const formatPlugin = (plugin: Plugin): string => plugin.id === 'app root' ? s.app('your app') : `plugin ${s.plugin(plugin.id)}` // TODO text similarity "did you mean...?" -export const formatUndefinedHookTasks = ( - undefinedHooks: HookTask[], +export const formatUndefinedCommandTasks = ( + undefinedHooks: CommandTask[], definedHooks: string[] -): string => `Hooks must be defined by a plugin before you can configure a task to run for them. In your Tool Kit configuration you've configured hooks that aren't defined: +): string => `TODO Hooks must be defined by a plugin before you can configure a task to run for them. In your Tool Kit configuration you've configured hooks that aren't defined: ${undefinedHooks.map((hook) => `- ${s.hook(hook.id)}`).join('\n')} @@ -126,7 +126,7 @@ ${uninstalledHooks.map((hook) => `- ${s.hook(hook.id || 'unknown event')}`).join Run ${s.task('dotcom-tool-kit --install')} to install these hooks. ` -type Missing = { hook: HookTask; tasks: string[] } +type Missing = { hook: CommandTask; tasks: string[] } const formatMissingTask = (missing: Missing): string => `- ${missing.tasks.map(s.task).join(', ')} ${s.dim( diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index ad3435406..9e27cd347 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -14,7 +14,7 @@ import resolveFrom from 'resolve-from' import type { Logger } from 'winston' import { PluginOptions, RawConfig, ValidPluginsConfig } from './config' import { Conflict, isConflict } from './conflict' -import type { HookTask } from './hook' +import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' import { isPlainObject } from 'lodash' @@ -213,45 +213,47 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger } } - // load plugin hook tasks. do this after loading child plugins, so - // parent hooks get assigned after child hooks and can override them - for (const [id, configHookTask] of Object.entries(plugin.rcFile.commands)) { - // handle conflicts between hooks from different plugins - const existingHookTask = config.hookTasks[id] - const newHookTask: HookTask = { + // load plugin command tasks. do this after loading child plugins, so + // parent commands get assigned after child commands and can override them + for (const [id, configCommandTask] of Object.entries(plugin.rcFile.commands)) { + // handle conflicts between commands from different plugins + const existingCommandTask = config.commandTasks[id] + const newCommandTask: CommandTask = { id, plugin, - tasks: Array.isArray(configHookTask) ? configHookTask : [configHookTask] + tasks: Array.isArray(configCommandTask) ? configCommandTask : [configCommandTask] } - if (existingHookTask) { - const existingFromDescendent = isDescendent(plugin, existingHookTask.plugin) + if (existingCommandTask) { + const existingFromDescendent = isDescendent(plugin, existingCommandTask.plugin) - // plugins can only override hook tasks from their descendents, otherwise that's a conflict - // return a conflict either listing this hook and the siblings, - // or merging in a previously-generated hook + // plugins can only override command tasks from their descendents, otherwise that's a conflict + // return a conflict either listing this command and the siblings, + // or merging in a previously-generated command if (!existingFromDescendent) { - const conflicting = isConflict(existingHookTask) ? existingHookTask.conflicting : [existingHookTask] + const conflicting = isConflict(existingCommandTask) + ? existingCommandTask.conflicting + : [existingCommandTask] - const conflict: Conflict = { + const conflict: Conflict = { plugin, - conflicting: conflicting.concat(newHookTask) + conflicting: conflicting.concat(newCommandTask) } - config.hookTasks[id] = conflict + config.commandTasks[id] = conflict } else { - // if we're here, any existing hook is from a child plugin, + // if we're here, any existing command is from a child plugin, // so the parent always overrides it - config.hookTasks[id] = newHookTask + config.commandTasks[id] = newCommandTask } } else { - // this hook task might not have been set yet, in which case use the new one - config.hookTasks[id] = newHookTask + // this command task might not have been set yet, in which case use the new one + config.commandTasks[id] = newCommandTask } } // merge options from this plugin's config with any options we've collected already - // TODO this is almost the exact same code as for hooks, refactor + // TODO this is almost the exact same code as for command tasks, refactor for (const [id, configOptions] of Object.entries(plugin.rcFile.options)) { // users can specify root options with the dotcom-tool-kit key to mirror // the name of the root npm package diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index 376a1a0b9..42f98fe2b 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -28,9 +28,9 @@ describe('cli', () => { resolvePlugin((plugin as Valid).value, validPluginConfig, logger) expect(() => validateConfig(validPluginConfig, logger)).toThrow(ToolKitError) - expect(validPluginConfig).toHaveProperty('hookTasks.build:ci.conflicting') - expect(validPluginConfig).toHaveProperty('hookTasks.build:remote.conflicting') - expect(validPluginConfig).toHaveProperty('hookTasks.build:local.conflicting') + expect(validPluginConfig).toHaveProperty('commandTasks.build:ci.conflicting') + expect(validPluginConfig).toHaveProperty('commandTasks.build:remote.conflicting') + expect(validPluginConfig).toHaveProperty('commandTasks.build:local.conflicting') }) it('should indicate when there are conflicts between plugins that are cousins in the tree', async () => { @@ -49,9 +49,9 @@ describe('cli', () => { resolvePlugin((plugin as Valid).value, validPluginConfig, logger) expect(() => validateConfig(validPluginConfig, logger)).toThrow(ToolKitError) - expect(config).toHaveProperty('hookTasks.build:ci.conflicting') - expect(config).toHaveProperty('hookTasks.build:remote.conflicting') - expect(config).toHaveProperty('hookTasks.build:local.conflicting') + expect(config).toHaveProperty('commandTasks.build:ci.conflicting') + expect(config).toHaveProperty('commandTasks.build:remote.conflicting') + expect(config).toHaveProperty('commandTasks.build:local.conflicting') }) it('should not have conflicts between multiple of the same plugin', async () => { @@ -99,8 +99,11 @@ describe('cli', () => { try { const validConfig = validateConfig(validPluginConfig, logger) - expect(validConfig).not.toHaveProperty('hookTasks.build:local.conflicting') - expect(validConfig.hookTasks['build:local'].tasks).toEqual(['WebpackDevelopment', 'BabelDevelopment']) + expect(validConfig).not.toHaveProperty('commandTasks.build:local.conflicting') + expect(validConfig.commandTasks['build:local'].tasks).toEqual([ + 'WebpackDevelopment', + 'BabelDevelopment' + ]) } catch (e) { if (e instanceof ToolKitError) { e.message += '\n' + e.details diff --git a/core/create/src/prompts/conflicts.ts b/core/create/src/prompts/conflicts.ts index 17af1e035..30c6852d3 100644 --- a/core/create/src/prompts/conflicts.ts +++ b/core/create/src/prompts/conflicts.ts @@ -31,7 +31,7 @@ export default async ({ error, logger, toolKitConfig, configPath }: ConflictsPar for (const conflict of error.conflicts) { const remainingTasks = conflict.conflictingTasks - orderedHooks[conflict.hook] = [] + orderedHooks[conflict.command] = [] const totalTasks = remainingTasks.length for (let i = 1; i <= totalTasks; i++) { @@ -39,7 +39,7 @@ export default async ({ error, logger, toolKitConfig, configPath }: ConflictsPar name: 'order', type: 'select', message: `Hook ${styles.hook( - conflict.hook + conflict.command )} has multiple tasks configured for it, so an order must be specified. \ Please select the ${ordinal(i)} package to run.`, choices: [ @@ -57,7 +57,7 @@ Please select the ${ordinal(i)} package to run.`, break } else { const { task } = remainingTasks.splice(nextIdx, 1)[0] - orderedHooks[conflict.hook].push(task) + orderedHooks[conflict.command].push(task) } } } diff --git a/lib/error/src/index.ts b/lib/error/src/index.ts index c6b735c1a..9dce4b049 100644 --- a/lib/error/src/index.ts +++ b/lib/error/src/index.ts @@ -8,15 +8,15 @@ export interface ConflictingTask { plugin: string } -export interface HookTaskConflict { - hook: string +export interface CommandTaskConflict { + command: string conflictingTasks: ConflictingTask[] } export class ToolKitConflictError extends ToolKitError { - conflicts: HookTaskConflict[] + conflicts: CommandTaskConflict[] - constructor(message: string, conflicts: HookTaskConflict[]) { + constructor(message: string, conflicts: CommandTaskConflict[]) { super(message) this.conflicts = conflicts } From e5def81a263a0dfa3572a934fa57928fad1d4c03 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 13 Oct 2023 18:07:14 +0100 Subject: [PATCH 020/321] refactor: rename main options schema to plugins --- core/cli/src/config.ts | 2 +- core/create/src/prompts/options.ts | 4 +- docs/developing-tool-kit.md | 4 +- lib/doppler/src/index.ts | 2 +- lib/options/src/index.ts | 2 +- lib/types/src/{schema.ts => plugins.ts} | 42 +++++++++---------- lib/types/src/schema/{ => plugins}/babel.ts | 0 .../src/schema/{ => plugins}/circleci.ts | 0 lib/types/src/schema/{ => plugins}/cypress.ts | 0 lib/types/src/schema/{ => plugins}/doppler.ts | 0 .../schema/{ => plugins}/dotcom-tool-kit.ts | 0 lib/types/src/schema/{ => plugins}/eslint.ts | 0 lib/types/src/schema/{ => plugins}/heroku.ts | 2 +- lib/types/src/schema/{ => plugins}/jest.ts | 0 .../schema/{ => plugins}/lint-staged-npm.ts | 0 lib/types/src/schema/{ => plugins}/mocha.ts | 0 lib/types/src/schema/{ => plugins}/n-test.ts | 0 .../src/schema/{ => plugins}/next-router.ts | 0 lib/types/src/schema/{ => plugins}/node.ts | 0 lib/types/src/schema/{ => plugins}/nodemon.ts | 0 lib/types/src/schema/{ => plugins}/pa11y.ts | 0 .../src/schema/{ => plugins}/prettier.ts | 0 .../src/schema/{ => plugins}/serverless.ts | 0 .../src/schema/{ => plugins}/typescript.ts | 0 .../{ => plugins}/upload-assets-to-s3.ts | 0 lib/types/src/schema/{ => plugins}/vault.ts | 0 lib/types/src/schema/{ => plugins}/webpack.ts | 0 lib/vault/src/index.ts | 2 +- plugins/babel/src/run-babel.ts | 2 +- plugins/babel/src/tasks/development.ts | 2 +- plugins/babel/src/tasks/production.ts | 2 +- plugins/cypress/src/tasks/cypress.ts | 2 +- plugins/eslint/src/tasks/eslint.ts | 2 +- plugins/heroku/src/tasks/production.ts | 2 +- plugins/heroku/src/tasks/review.ts | 2 +- plugins/heroku/src/tasks/staging.ts | 2 +- plugins/jest/src/run-jest.ts | 2 +- plugins/jest/src/tasks/ci.ts | 8 ++-- plugins/jest/src/tasks/local.ts | 6 +-- plugins/mocha/src/tasks/mocha.ts | 2 +- plugins/n-test/src/tasks/n-test.ts | 2 +- plugins/next-router/src/tasks/next-router.ts | 2 +- plugins/node/src/tasks/node.ts | 2 +- plugins/nodemon/src/tasks/nodemon.ts | 2 +- plugins/pa11y/src/tasks/pa11y.ts | 2 +- plugins/prettier/src/tasks/prettier.ts | 2 +- plugins/serverless/src/tasks/deploy.ts | 2 +- plugins/serverless/src/tasks/provision.ts | 2 +- plugins/serverless/src/tasks/run.ts | 2 +- plugins/typescript/src/tasks/typescript.ts | 2 +- .../src/tasks/upload-assets-to-s3.ts | 2 +- .../test/tasks/upload-assets-to-s3.test.ts | 2 +- plugins/webpack/src/run-webpack.ts | 2 +- plugins/webpack/src/tasks/development.ts | 2 +- plugins/webpack/src/tasks/production.ts | 2 +- plugins/webpack/src/tasks/watch.ts | 2 +- 56 files changed, 63 insertions(+), 63 deletions(-) rename lib/types/src/{schema.ts => plugins.ts} (67%) rename lib/types/src/schema/{ => plugins}/babel.ts (100%) rename lib/types/src/schema/{ => plugins}/circleci.ts (100%) rename lib/types/src/schema/{ => plugins}/cypress.ts (100%) rename lib/types/src/schema/{ => plugins}/doppler.ts (100%) rename lib/types/src/schema/{ => plugins}/dotcom-tool-kit.ts (100%) rename lib/types/src/schema/{ => plugins}/eslint.ts (100%) rename lib/types/src/schema/{ => plugins}/heroku.ts (98%) rename lib/types/src/schema/{ => plugins}/jest.ts (100%) rename lib/types/src/schema/{ => plugins}/lint-staged-npm.ts (100%) rename lib/types/src/schema/{ => plugins}/mocha.ts (100%) rename lib/types/src/schema/{ => plugins}/n-test.ts (100%) rename lib/types/src/schema/{ => plugins}/next-router.ts (100%) rename lib/types/src/schema/{ => plugins}/node.ts (100%) rename lib/types/src/schema/{ => plugins}/nodemon.ts (100%) rename lib/types/src/schema/{ => plugins}/pa11y.ts (100%) rename lib/types/src/schema/{ => plugins}/prettier.ts (100%) rename lib/types/src/schema/{ => plugins}/serverless.ts (100%) rename lib/types/src/schema/{ => plugins}/typescript.ts (100%) rename lib/types/src/schema/{ => plugins}/upload-assets-to-s3.ts (100%) rename lib/types/src/schema/{ => plugins}/vault.ts (100%) rename lib/types/src/schema/{ => plugins}/webpack.ts (100%) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 3ee4f9049..713a89178 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -18,7 +18,7 @@ import { unwrapValidated, Validated } from '@dotcom-tool-kit/types' -import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/schema' +import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' import { InvalidOption, formatTaskConflicts, diff --git a/core/create/src/prompts/options.ts b/core/create/src/prompts/options.ts index 2b82503d2..ba1f2bdb2 100644 --- a/core/create/src/prompts/options.ts +++ b/core/create/src/prompts/options.ts @@ -1,6 +1,6 @@ import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' import type { RCFile } from '@dotcom-tool-kit/types' -import type { PromptGenerators } from '@dotcom-tool-kit/types/src/schema' +import type { PromptGenerators } from '@dotcom-tool-kit/types/src/plugins' import type { RawConfig } from 'dotcom-tool-kit/lib/config' import { promises as fs } from 'fs' import YAML from 'yaml' @@ -208,7 +208,7 @@ export default async ({ // TODO allow different schemas for tasks within a plugin const { Schema, generators: SchemaGenerators } = // eslint-disable-next-line @typescript-eslint/no-var-requires - require(`@dotcom-tool-kit/types/lib/schema/${pluginName}`) + require(`@dotcom-tool-kit/types/lib/schema/plugins/${pluginName}`) options = Schema generators = SchemaGenerators } catch (err) { diff --git a/docs/developing-tool-kit.md b/docs/developing-tool-kit.md index 193d4dd6f..c1f2aa6a4 100644 --- a/docs/developing-tool-kit.md +++ b/docs/developing-tool-kit.md @@ -94,7 +94,7 @@ This lets different plugins define the same abstractly labelled hooks with diffe #### Defining options -Plugins can define options that a user can configure in their repo's `.toolkitrc.yml`. We use the [`zod` library](https://zod.dev) to specify the schema, which allows us to define what we expect the options to look like and use this specification to validate the options we receive as well as generate TypeScript types for them. Options are defined in the `@dotcom-tool-kit/types` package, in the `schema` files. Create a file in [`src/schema`](../lib/types/src/schema) for your plugin, which should export a `NameOfPluginSchema` object (that should also be exported as `Schema`), and a `NameOfPluginOptions` type that uses the `SchemaOutput` generic type. +Plugins can define options that a user can configure in their repo's `.toolkitrc.yml`. We use the [`zod` library](https://zod.dev) to specify the schema, which allows us to define what we expect the options to look like and use this specification to validate the options we receive as well as generate TypeScript types for them. Options are defined in the `@dotcom-tool-kit/types` package, in the `schema` files. Create a file in [`src/schema`](../lib/types/src/schema/plugins) for your plugin, which should export a `NameOfPluginSchema` object (that should also be exported as `Schema`), and a `NameOfPluginOptions` type that uses the `SchemaOutput` generic type. ```typescript import { z } from 'zod' @@ -136,7 +136,7 @@ To avoid boilerplate for tasks (the most common use case for options), when defi ```typescript import { Task } from '@dotcom-tool-kit/types' -import { ESLintOptions, ESLintSchema } from '@dotcom-tool-kit/types/lib/schema/eslint' +import { ESLintOptions, ESLintSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/eslint' export default class Eslint extends Task { static description = '' diff --git a/lib/doppler/src/index.ts b/lib/doppler/src/index.ts index 25375fe62..03d0d11ba 100644 --- a/lib/doppler/src/index.ts +++ b/lib/doppler/src/index.ts @@ -7,7 +7,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { styles, waitOnExit } from '@dotcom-tool-kit/logger' import { getOptions } from '@dotcom-tool-kit/options' import * as Vault from '@dotcom-tool-kit/vault' -import type { DopplerOptions as ConfiguredDopplerOptions } from '@dotcom-tool-kit/types/lib/schema/doppler' +import type { DopplerOptions as ConfiguredDopplerOptions } from '@dotcom-tool-kit/types/lib/schema/plugins/doppler' export type Environment = 'prod' | 'ci' | 'dev' diff --git a/lib/options/src/index.ts b/lib/options/src/index.ts index 230d1dba5..8495f29a5 100644 --- a/lib/options/src/index.ts +++ b/lib/options/src/index.ts @@ -1,4 +1,4 @@ -import type { Options } from '@dotcom-tool-kit/types/src/schema' +import type { Options } from '@dotcom-tool-kit/types/src/plugins' const options: Partial = {} diff --git a/lib/types/src/schema.ts b/lib/types/src/plugins.ts similarity index 67% rename from lib/types/src/schema.ts rename to lib/types/src/plugins.ts index 75dbba574..a68ff5cdb 100644 --- a/lib/types/src/schema.ts +++ b/lib/types/src/plugins.ts @@ -32,27 +32,27 @@ export type PromptGenerators = T extends z.ZodObject } : never -import { BabelSchema } from './schema/babel' -import { CircleCISchema } from './schema/circleci' -import { CypressSchema } from './schema/cypress' -import { DopplerSchema } from './schema/doppler' -import { RootSchema } from './schema/dotcom-tool-kit' -import { ESLintSchema } from './schema/eslint' -import { HerokuSchema } from './schema/heroku' -import { LintStagedNpmSchema } from './schema/lint-staged-npm' -import { JestSchema } from './schema/jest' -import { MochaSchema } from './schema/mocha' -import { SmokeTestSchema } from './schema/n-test' -import { NextRouterSchema } from './schema/next-router' -import { NodeSchema } from './schema/node' -import { NodemonSchema } from './schema/nodemon' -import { Pa11ySchema } from './schema/pa11y' -import { PrettierSchema } from './schema/prettier' -import { ServerlessSchema } from './schema/serverless' -import { TypeScriptSchema } from './schema/typescript' -import { UploadAssetsToS3Schema } from './schema/upload-assets-to-s3' -import { VaultSchema } from './schema/vault' -import { WebpackSchema } from './schema/webpack' +import { BabelSchema } from './schema/plugins/babel' +import { CircleCISchema } from './schema/plugins/circleci' +import { CypressSchema } from './schema/plugins/cypress' +import { DopplerSchema } from './schema/plugins/doppler' +import { RootSchema } from './schema/plugins/dotcom-tool-kit' +import { ESLintSchema } from './schema/plugins/eslint' +import { HerokuSchema } from './schema/plugins/heroku' +import { LintStagedNpmSchema } from './schema/plugins/lint-staged-npm' +import { JestSchema } from './schema/plugins/jest' +import { MochaSchema } from './schema/plugins/mocha' +import { SmokeTestSchema } from './schema/plugins/n-test' +import { NextRouterSchema } from './schema/plugins/next-router' +import { NodeSchema } from './schema/plugins/node' +import { NodemonSchema } from './schema/plugins/nodemon' +import { Pa11ySchema } from './schema/plugins/pa11y' +import { PrettierSchema } from './schema/plugins/prettier' +import { ServerlessSchema } from './schema/plugins/serverless' +import { TypeScriptSchema } from './schema/plugins/typescript' +import { UploadAssetsToS3Schema } from './schema/plugins/upload-assets-to-s3' +import { VaultSchema } from './schema/plugins/vault' +import { WebpackSchema } from './schema/plugins/webpack' export const Schemas = { 'app root': RootSchema, diff --git a/lib/types/src/schema/babel.ts b/lib/types/src/schema/plugins/babel.ts similarity index 100% rename from lib/types/src/schema/babel.ts rename to lib/types/src/schema/plugins/babel.ts diff --git a/lib/types/src/schema/circleci.ts b/lib/types/src/schema/plugins/circleci.ts similarity index 100% rename from lib/types/src/schema/circleci.ts rename to lib/types/src/schema/plugins/circleci.ts diff --git a/lib/types/src/schema/cypress.ts b/lib/types/src/schema/plugins/cypress.ts similarity index 100% rename from lib/types/src/schema/cypress.ts rename to lib/types/src/schema/plugins/cypress.ts diff --git a/lib/types/src/schema/doppler.ts b/lib/types/src/schema/plugins/doppler.ts similarity index 100% rename from lib/types/src/schema/doppler.ts rename to lib/types/src/schema/plugins/doppler.ts diff --git a/lib/types/src/schema/dotcom-tool-kit.ts b/lib/types/src/schema/plugins/dotcom-tool-kit.ts similarity index 100% rename from lib/types/src/schema/dotcom-tool-kit.ts rename to lib/types/src/schema/plugins/dotcom-tool-kit.ts diff --git a/lib/types/src/schema/eslint.ts b/lib/types/src/schema/plugins/eslint.ts similarity index 100% rename from lib/types/src/schema/eslint.ts rename to lib/types/src/schema/plugins/eslint.ts diff --git a/lib/types/src/schema/heroku.ts b/lib/types/src/schema/plugins/heroku.ts similarity index 98% rename from lib/types/src/schema/heroku.ts rename to lib/types/src/schema/plugins/heroku.ts index 7b6e09a02..9912a6689 100644 --- a/lib/types/src/schema/heroku.ts +++ b/lib/types/src/schema/plugins/heroku.ts @@ -1,4 +1,4 @@ -import { SchemaPromptGenerator, PromptGenerators } from '../schema' +import { SchemaPromptGenerator, PromptGenerators } from '../../plugins' import { waitOnExit } from '@dotcom-tool-kit/logger' diff --git a/lib/types/src/schema/jest.ts b/lib/types/src/schema/plugins/jest.ts similarity index 100% rename from lib/types/src/schema/jest.ts rename to lib/types/src/schema/plugins/jest.ts diff --git a/lib/types/src/schema/lint-staged-npm.ts b/lib/types/src/schema/plugins/lint-staged-npm.ts similarity index 100% rename from lib/types/src/schema/lint-staged-npm.ts rename to lib/types/src/schema/plugins/lint-staged-npm.ts diff --git a/lib/types/src/schema/mocha.ts b/lib/types/src/schema/plugins/mocha.ts similarity index 100% rename from lib/types/src/schema/mocha.ts rename to lib/types/src/schema/plugins/mocha.ts diff --git a/lib/types/src/schema/n-test.ts b/lib/types/src/schema/plugins/n-test.ts similarity index 100% rename from lib/types/src/schema/n-test.ts rename to lib/types/src/schema/plugins/n-test.ts diff --git a/lib/types/src/schema/next-router.ts b/lib/types/src/schema/plugins/next-router.ts similarity index 100% rename from lib/types/src/schema/next-router.ts rename to lib/types/src/schema/plugins/next-router.ts diff --git a/lib/types/src/schema/node.ts b/lib/types/src/schema/plugins/node.ts similarity index 100% rename from lib/types/src/schema/node.ts rename to lib/types/src/schema/plugins/node.ts diff --git a/lib/types/src/schema/nodemon.ts b/lib/types/src/schema/plugins/nodemon.ts similarity index 100% rename from lib/types/src/schema/nodemon.ts rename to lib/types/src/schema/plugins/nodemon.ts diff --git a/lib/types/src/schema/pa11y.ts b/lib/types/src/schema/plugins/pa11y.ts similarity index 100% rename from lib/types/src/schema/pa11y.ts rename to lib/types/src/schema/plugins/pa11y.ts diff --git a/lib/types/src/schema/prettier.ts b/lib/types/src/schema/plugins/prettier.ts similarity index 100% rename from lib/types/src/schema/prettier.ts rename to lib/types/src/schema/plugins/prettier.ts diff --git a/lib/types/src/schema/serverless.ts b/lib/types/src/schema/plugins/serverless.ts similarity index 100% rename from lib/types/src/schema/serverless.ts rename to lib/types/src/schema/plugins/serverless.ts diff --git a/lib/types/src/schema/typescript.ts b/lib/types/src/schema/plugins/typescript.ts similarity index 100% rename from lib/types/src/schema/typescript.ts rename to lib/types/src/schema/plugins/typescript.ts diff --git a/lib/types/src/schema/upload-assets-to-s3.ts b/lib/types/src/schema/plugins/upload-assets-to-s3.ts similarity index 100% rename from lib/types/src/schema/upload-assets-to-s3.ts rename to lib/types/src/schema/plugins/upload-assets-to-s3.ts diff --git a/lib/types/src/schema/vault.ts b/lib/types/src/schema/plugins/vault.ts similarity index 100% rename from lib/types/src/schema/vault.ts rename to lib/types/src/schema/plugins/vault.ts diff --git a/lib/types/src/schema/webpack.ts b/lib/types/src/schema/plugins/webpack.ts similarity index 100% rename from lib/types/src/schema/webpack.ts rename to lib/types/src/schema/plugins/webpack.ts diff --git a/lib/vault/src/index.ts b/lib/vault/src/index.ts index bd4a8ef96..1f5927672 100644 --- a/lib/vault/src/index.ts +++ b/lib/vault/src/index.ts @@ -5,7 +5,7 @@ import os from 'os' import type { Logger } from 'winston' import { ToolKitError } from '@dotcom-tool-kit/error' import { getOptions } from '@dotcom-tool-kit/options' -import { VaultOptions } from '@dotcom-tool-kit/types/lib/schema/vault' +import { VaultOptions } from '@dotcom-tool-kit/types/lib/schema/plugins/vault' const VAULT_ROLE_ID = process.env.VAULT_ROLE_ID const VAULT_SECRET_ID = process.env.VAULT_SECRET_ID diff --git a/plugins/babel/src/run-babel.ts b/plugins/babel/src/run-babel.ts index 1f3f74d48..60484fa9a 100644 --- a/plugins/babel/src/run-babel.ts +++ b/plugins/babel/src/run-babel.ts @@ -1,6 +1,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookConsole } from '@dotcom-tool-kit/logger' -import type { BabelOptions } from '@dotcom-tool-kit/types/src/schema/babel' +import type { BabelOptions } from '@dotcom-tool-kit/types/lib/schema/plugins/babel' import * as babel from '@babel/core' import fg from 'fast-glob' import { promises as fs } from 'fs' diff --git a/plugins/babel/src/tasks/development.ts b/plugins/babel/src/tasks/development.ts index 97186f885..352655aaa 100644 --- a/plugins/babel/src/tasks/development.ts +++ b/plugins/babel/src/tasks/development.ts @@ -1,6 +1,6 @@ import { runBabel } from '../run-babel' import { Task } from '@dotcom-tool-kit/types' -import { BabelSchema } from '@dotcom-tool-kit/types/lib/schema/babel' +import { BabelSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/babel' export default class BabelDevelopment extends Task { static description = 'build babel' diff --git a/plugins/babel/src/tasks/production.ts b/plugins/babel/src/tasks/production.ts index 03fb0e4f3..d36f341c5 100644 --- a/plugins/babel/src/tasks/production.ts +++ b/plugins/babel/src/tasks/production.ts @@ -1,6 +1,6 @@ import { runBabel } from '../run-babel' import { Task } from '@dotcom-tool-kit/types' -import { BabelSchema } from '@dotcom-tool-kit/types/lib/schema/babel' +import { BabelSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/babel' export default class BabelProduction extends Task { static description = 'build babel' diff --git a/plugins/cypress/src/tasks/cypress.ts b/plugins/cypress/src/tasks/cypress.ts index 7e6876145..2c2040ed9 100644 --- a/plugins/cypress/src/tasks/cypress.ts +++ b/plugins/cypress/src/tasks/cypress.ts @@ -3,7 +3,7 @@ import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { readState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/types' -import { CypressSchema } from '@dotcom-tool-kit/types/src/schema/cypress' +import { CypressSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/cypress' export class CypressLocal extends Task { async run(): Promise { diff --git a/plugins/eslint/src/tasks/eslint.ts b/plugins/eslint/src/tasks/eslint.ts index b55f0fea6..f40b1bbf2 100644 --- a/plugins/eslint/src/tasks/eslint.ts +++ b/plugins/eslint/src/tasks/eslint.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { styles } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { ESLintSchema } from '@dotcom-tool-kit/types/lib/schema/eslint' +import { ESLintSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/eslint' import { ESLint } from 'eslint' export default class Eslint extends Task { diff --git a/plugins/heroku/src/tasks/production.ts b/plugins/heroku/src/tasks/production.ts index 5b2416466..9a26dd60e 100644 --- a/plugins/heroku/src/tasks/production.ts +++ b/plugins/heroku/src/tasks/production.ts @@ -2,7 +2,7 @@ import { Task } from '@dotcom-tool-kit/types' import { ToolKitError } from '@dotcom-tool-kit/error' import { readState } from '@dotcom-tool-kit/state' import { styles } from '@dotcom-tool-kit/logger' -import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/heroku' +import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/heroku' import type { HerokuApiResGetApp } from 'heroku-client' import heroku, { extractHerokuError } from '../herokuClient' import { scaleDyno } from '../scaleDyno' diff --git a/plugins/heroku/src/tasks/review.ts b/plugins/heroku/src/tasks/review.ts index b3b529bf1..0a23edc15 100644 --- a/plugins/heroku/src/tasks/review.ts +++ b/plugins/heroku/src/tasks/review.ts @@ -4,7 +4,7 @@ import { buildHerokuReviewApp } from '../buildHerokuReviewApp' import { gtg } from '../gtg' import { setStageConfigVars } from '../setConfigVars' import { writeState } from '@dotcom-tool-kit/state' -import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/heroku' +import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/heroku' import { ToolKitError } from '@dotcom-tool-kit/error' import herokuClient, { extractHerokuError } from '../herokuClient' import type { HerokuApiResPipeline } from 'heroku-client' diff --git a/plugins/heroku/src/tasks/staging.ts b/plugins/heroku/src/tasks/staging.ts index 1653077a9..d9cce3fb1 100644 --- a/plugins/heroku/src/tasks/staging.ts +++ b/plugins/heroku/src/tasks/staging.ts @@ -7,7 +7,7 @@ import { repeatedCheckForBuildSuccess } from '../repeatedCheckForBuildSuccess' import { scaleDyno } from '../scaleDyno' import { gtg } from '../gtg' import { getPipelineCouplings } from '../getPipelineCouplings' -import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/heroku' +import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/heroku' import { setStagingSlug } from '../setStagingSlug' export default class HerokuStaging extends Task { diff --git a/plugins/jest/src/run-jest.ts b/plugins/jest/src/run-jest.ts index 99ce6fbf5..0b28ba4dc 100644 --- a/plugins/jest/src/run-jest.ts +++ b/plugins/jest/src/run-jest.ts @@ -1,6 +1,6 @@ import { fork } from 'node:child_process' import { readFile } from 'node:fs/promises' -import type { JestOptions, JestMode } from '@dotcom-tool-kit/types/lib/schema/jest' +import type { JestOptions, JestMode } from '@dotcom-tool-kit/types/lib/schema/plugins/jest' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' const jestCLIPath = require.resolve('jest-cli/bin/jest') diff --git a/plugins/jest/src/tasks/ci.ts b/plugins/jest/src/tasks/ci.ts index 06a8b95c2..a8135790e 100644 --- a/plugins/jest/src/tasks/ci.ts +++ b/plugins/jest/src/tasks/ci.ts @@ -1,11 +1,11 @@ import { Task } from '@dotcom-tool-kit/types' -import { JestSchema } from '@dotcom-tool-kit/types/src/schema/jest' +import { JestSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/jest' import runJest from '../run-jest' export default class JestCI extends Task { - static description = '' - - async run(): Promise { + static description = '' + + async run(): Promise { await runJest(this.logger, 'ci', this.options) } } diff --git a/plugins/jest/src/tasks/local.ts b/plugins/jest/src/tasks/local.ts index a17f09c29..f0f7cda36 100644 --- a/plugins/jest/src/tasks/local.ts +++ b/plugins/jest/src/tasks/local.ts @@ -1,11 +1,11 @@ import { Task } from '@dotcom-tool-kit/types' -import { JestSchema } from '@dotcom-tool-kit/types/src/schema/jest' +import { JestSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/jest' import runJest from '../run-jest' export default class JestLocal extends Task { - static description = '' + static description = '' - async run(): Promise { + async run(): Promise { await runJest(this.logger, 'local', this.options) } } diff --git a/plugins/mocha/src/tasks/mocha.ts b/plugins/mocha/src/tasks/mocha.ts index ce2a6929b..6919e6dac 100644 --- a/plugins/mocha/src/tasks/mocha.ts +++ b/plugins/mocha/src/tasks/mocha.ts @@ -1,7 +1,7 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' import { glob } from 'glob' -import { MochaSchema } from '@dotcom-tool-kit/types/lib/schema/mocha' +import { MochaSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/mocha' import { fork } from 'child_process' import { promisify } from 'util' const mochaCLIPath = require.resolve('mocha/bin/mocha') diff --git a/plugins/n-test/src/tasks/n-test.ts b/plugins/n-test/src/tasks/n-test.ts index 1d9a02163..23d823e5d 100644 --- a/plugins/n-test/src/tasks/n-test.ts +++ b/plugins/n-test/src/tasks/n-test.ts @@ -1,6 +1,6 @@ import { styles } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { SmokeTestSchema } from '@dotcom-tool-kit/types/lib/schema/n-test' +import { SmokeTestSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/n-test' import { SmokeTest } from '@financial-times/n-test' import { readState } from '@dotcom-tool-kit/state' diff --git a/plugins/next-router/src/tasks/next-router.ts b/plugins/next-router/src/tasks/next-router.ts index 6b2ac5654..87580f560 100644 --- a/plugins/next-router/src/tasks/next-router.ts +++ b/plugins/next-router/src/tasks/next-router.ts @@ -5,7 +5,7 @@ import { readState } from '@dotcom-tool-kit/state' import { hookConsole, hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { ToolKitError } from '@dotcom-tool-kit/error' import { fork } from 'child_process' -import { NextRouterSchema } from '@dotcom-tool-kit/types/lib/schema/next-router' +import { NextRouterSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/next-router' export default class NextRouter extends Task { static description = '' diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index 2fccd3f67..6f6e132f0 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -2,7 +2,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookConsole, hookFork, styles } from '@dotcom-tool-kit/logger' import { writeState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/types' -import { NodeSchema } from '@dotcom-tool-kit/types/lib/schema/node' +import { NodeSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/node' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { fork } from 'child_process' import getPort from 'get-port' diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index 93f25dff0..50ec84717 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -1,6 +1,6 @@ import { hookFork } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { NodemonSchema } from '@dotcom-tool-kit/types/lib/schema/nodemon' +import { NodemonSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/nodemon' import { writeState } from '@dotcom-tool-kit/state' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import getPort from 'get-port' diff --git a/plugins/pa11y/src/tasks/pa11y.ts b/plugins/pa11y/src/tasks/pa11y.ts index 7b627366b..f59845015 100644 --- a/plugins/pa11y/src/tasks/pa11y.ts +++ b/plugins/pa11y/src/tasks/pa11y.ts @@ -1,6 +1,6 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import type { Pa11ySchema } from '@dotcom-tool-kit/types/lib/schema/pa11y' +import type { Pa11ySchema } from '@dotcom-tool-kit/types/lib/schema/plugins/pa11y' import { fork } from 'child_process' import { readState } from '@dotcom-tool-kit/state' diff --git a/plugins/prettier/src/tasks/prettier.ts b/plugins/prettier/src/tasks/prettier.ts index f1df42d51..65bd1189f 100644 --- a/plugins/prettier/src/tasks/prettier.ts +++ b/plugins/prettier/src/tasks/prettier.ts @@ -1,5 +1,5 @@ import prettier from 'prettier' -import { PrettierOptions, PrettierSchema } from '@dotcom-tool-kit/types/lib/schema/prettier' +import { PrettierOptions, PrettierSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/prettier' import { promises as fsp } from 'fs' import fg from 'fast-glob' import { hookConsole, styles } from '@dotcom-tool-kit/logger' diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index a4d3dfdfd..cfa85068f 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/serverless' +import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/serverless' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { getOptions } from '@dotcom-tool-kit/options' import { spawn } from 'child_process' diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index 1ad43485a..366cb2b38 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/serverless' +import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/serverless' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { spawn } from 'child_process' import { getOptions } from '@dotcom-tool-kit/options' diff --git a/plugins/serverless/src/tasks/run.ts b/plugins/serverless/src/tasks/run.ts index b64e7ba04..240afd6e4 100644 --- a/plugins/serverless/src/tasks/run.ts +++ b/plugins/serverless/src/tasks/run.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/serverless' +import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/serverless' import { spawn } from 'child_process' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { hookConsole, hookFork } from '@dotcom-tool-kit/logger' diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index 10c6b08d6..510313ce0 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -1,6 +1,6 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import type { TypeScriptSchema } from '@dotcom-tool-kit/types/lib/schema/typescript' +import type { TypeScriptSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/typescript' import { fork } from 'child_process' const tscPath = require.resolve('typescript/bin/tsc') diff --git a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts index 698144b63..aa3bbda77 100644 --- a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts +++ b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts @@ -9,7 +9,7 @@ import { styles } from '@dotcom-tool-kit/logger' import { UploadAssetsToS3Options, UploadAssetsToS3Schema -} from '@dotcom-tool-kit/types/lib/schema/upload-assets-to-s3' +} from '@dotcom-tool-kit/types/lib/schema/plugins/upload-assets-to-s3' export default class UploadAssetsToS3 extends Task { static description = '' diff --git a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts index bbae7e63b..6acc1985d 100644 --- a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts +++ b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach } from '@jest/globals' import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3' -import { UploadAssetsToS3Options } from '@dotcom-tool-kit/types/lib/schema/upload-assets-to-s3' +import { UploadAssetsToS3Options } from '@dotcom-tool-kit/types/lib/schema/plugins/upload-assets-to-s3' import * as path from 'path' import winston, { Logger } from 'winston' import UploadAssetsToS3 from '../../src/tasks/upload-assets-to-s3' diff --git a/plugins/webpack/src/run-webpack.ts b/plugins/webpack/src/run-webpack.ts index f0ff8b745..5ece3d837 100644 --- a/plugins/webpack/src/run-webpack.ts +++ b/plugins/webpack/src/run-webpack.ts @@ -1,6 +1,6 @@ import { fork } from 'child_process' import { Logger } from 'winston' -import type { WebpackOptions } from '@dotcom-tool-kit/types/lib/schema/webpack' +import type { WebpackOptions } from '@dotcom-tool-kit/types/lib/schema/plugins/webpack' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' const webpackCLIPath = require.resolve('webpack-cli/bin/cli') diff --git a/plugins/webpack/src/tasks/development.ts b/plugins/webpack/src/tasks/development.ts index 25e1cf2d3..737240b9e 100644 --- a/plugins/webpack/src/tasks/development.ts +++ b/plugins/webpack/src/tasks/development.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/webpack' +import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/webpack' import runWebpack from '../run-webpack' export default class WebpackDevelopment extends Task { diff --git a/plugins/webpack/src/tasks/production.ts b/plugins/webpack/src/tasks/production.ts index 882de4a22..d9027c27a 100644 --- a/plugins/webpack/src/tasks/production.ts +++ b/plugins/webpack/src/tasks/production.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/webpack' +import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/webpack' import runWebpack from '../run-webpack' export default class WebpackProduction extends Task { diff --git a/plugins/webpack/src/tasks/watch.ts b/plugins/webpack/src/tasks/watch.ts index 79d8f344e..336a34da9 100644 --- a/plugins/webpack/src/tasks/watch.ts +++ b/plugins/webpack/src/tasks/watch.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/webpack' +import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/webpack' import runWebpack from '../run-webpack' export default class WebpackWatch extends Task { From dad4056aeceb2b3a39eac94fe9a93a89728fe13e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 15 Nov 2023 09:00:51 +0000 Subject: [PATCH 021/321] refactor: use an EntryPoint object for tasks and hooks in the config instead of just strings, which can easily be confused for strings from somewhere else. in the very near future the entry point is not just going to be the plugin root; this refactor makes that easier. --- core/cli/src/config.ts | 17 +++++++++++------ core/cli/src/index.ts | 6 +++--- core/cli/src/messages.ts | 14 +++++++------- core/cli/src/plugin.ts | 18 +++++++++++++----- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 713a89178..d6961645b 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -38,14 +38,19 @@ export interface PluginOptions { forPlugin: Plugin } +export interface EntryPoint { + plugin: Plugin + modulePath: string +} + export interface RawConfig { root: string plugins: { [id: string]: Validated } resolvedPlugins: Set - tasks: { [id: string]: string | Conflict } + tasks: { [id: string]: EntryPoint | Conflict } commandTasks: { [id: string]: CommandTask | Conflict } options: { [id: string]: PluginOptions | Conflict | undefined } - hooks: { [id: string]: string | Conflict } + hooks: { [id: string]: EntryPoint | Conflict } } export type ValidPluginsConfig = Omit & { @@ -61,18 +66,18 @@ export type ValidOptions = { } export type ValidConfig = Omit & { - tasks: { [id: string]: string } + tasks: { [id: string]: EntryPoint } commandTasks: { [id: string]: CommandTask } options: ValidOptions - hooks: { [id: string]: string } + hooks: { [id: string]: EntryPoint } } const coreRoot = path.resolve(__dirname, '../') export const loadHooks = async (logger: Logger, config: ValidConfig): Promise[]>> => { const hookResults = await Promise.all( - Object.entries(config.hooks).map(async ([hookName, pluginId]) => { - const hookPlugin = await importPlugin(pluginId) + Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { + const hookPlugin = await importPlugin(entryPoint.modulePath) return flatMapValidated(hookPlugin, (plugin) => { const pluginHooks = validatePluginHooks(plugin as RawPluginModule) diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 89f583a34..3d887bc49 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -43,15 +43,15 @@ const loadTasks = async ( ): Promise>> => { const taskResults = await Promise.all( taskNames.map(async (taskName) => { - const pluginId = config.tasks[taskName] - const taskPlugin = await importPlugin(pluginId) + const entryPoint = config.tasks[taskName] + const taskPlugin = await importPlugin(entryPoint.modulePath) return flatMapValidated(taskPlugin, (plugin) => { const pluginTasks = validatePluginTasks(plugin as RawPluginModule) return mapValidated(pluginTasks, (tasks) => [ taskName, - new tasks[taskName](logger, taskName, getOptions(pluginId as OptionKey) ?? {}) + new tasks[taskName](logger, taskName, getOptions(entryPoint.plugin.id as OptionKey) ?? {}) ]) }) }) diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 737f5a71d..25f89905d 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -2,28 +2,28 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' import type { Hook, Plugin } from '@dotcom-tool-kit/types' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' -import type { PluginOptions } from './config' +import type { EntryPoint, PluginOptions } from './config' import type { Conflict } from './conflict' import type { CommandTask } from './command' -const formatTaskConflict = ([key, conflict]: [string, Conflict]): string => +const formatTaskConflict = ([key, conflict]: [string, Conflict]): string => `- ${s.task(key ?? 'unknown task')} ${s.dim('from plugins')} ${conflict.conflicting - .map((task) => s.plugin(task ?? 'unknown plugin')) + .map((entryPoint) => s.plugin(entryPoint.plugin.id ?? 'unknown plugin')) .join(s.dim(', '))}` -export const formatTaskConflicts = (conflicts: [string, Conflict][]): string => `${s.heading( +export const formatTaskConflicts = (conflicts: [string, Conflict][]): string => `${s.heading( 'There are multiple plugins that include the same tasks' )}: ${conflicts.map(formatTaskConflict).join('\n')} You must resolve this conflict by removing all but one of these plugins.` -const formatHookConflict = ([key, conflict]: [string, Conflict]): string => +const formatHookConflict = ([key, conflict]: [string, Conflict]): string => `- ${s.hook(key ?? 'unknown hook')} ${s.dim('from plugins')} ${conflict.conflicting - .map((task) => s.plugin(task ?? 'unknown plugin')) + .map((entryPoint) => s.plugin(entryPoint.plugin.id ?? 'unknown plugin')) .join(s.dim(', '))}` -export const formatHookConflicts = (conflicts: [string, Conflict][]): string => `${s.heading( +export const formatHookConflicts = (conflicts: [string, Conflict][]): string => `${s.heading( 'There are multiple plugins that include the same hooks' )}: ${conflicts.map(formatHookConflict).join('\n')} diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 9e27cd347..e769eb08b 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -12,7 +12,7 @@ import { } from '@dotcom-tool-kit/types' import resolveFrom from 'resolve-from' import type { Logger } from 'winston' -import { PluginOptions, RawConfig, ValidPluginsConfig } from './config' +import { EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' import { Conflict, isConflict } from './conflict' import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' @@ -183,16 +183,20 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger // add plugin tasks to our task registry, handling any conflicts for (const taskName of plugin.rcFile.tasks || []) { const existingTaskId = config.tasks[taskName] + const entryPoint: EntryPoint = { + plugin, + modulePath: plugin.id + } if (existingTaskId) { const conflicting = isConflict(existingTaskId) ? existingTaskId.conflicting : [existingTaskId] config.tasks[taskName] = { plugin, - conflicting: conflicting.concat(plugin.id) + conflicting: conflicting.concat(entryPoint) } } else { - config.tasks[taskName] = plugin.id + config.tasks[taskName] = entryPoint } } @@ -200,16 +204,20 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger // TODO refactor with command conflict handler for (const hookName of plugin.rcFile.installs || []) { const existingHookId = config.hooks[hookName] + const entryPoint: EntryPoint = { + plugin, + modulePath: plugin.id + } if (existingHookId) { const conflicting = isConflict(existingHookId) ? existingHookId.conflicting : [existingHookId] config.hooks[hookName] = { plugin, - conflicting: conflicting.concat(plugin.id) + conflicting: conflicting.concat(entryPoint) } } else { - config.hooks[hookName] = plugin.id + config.hooks[hookName] = entryPoint } } From ce2dd4bf29b81e0160c7a70d2dde3623cb5e9d7a Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 13 Oct 2023 15:18:51 +0100 Subject: [PATCH 022/321] chore!: remove all current concrete hook subclasses --- plugins/circleci-deploy/index.js | 0 plugins/circleci-deploy/src/index.ts | 144 --------------------- plugins/circleci-deploy/test/index.test.ts | 18 --- plugins/circleci-npm/index.js | 0 plugins/circleci-npm/src/index.ts | 21 --- plugins/circleci-npm/test/index.test.ts | 12 -- plugins/circleci/src/index.ts | 30 ----- plugins/cypress/src/index.ts | 10 -- plugins/heroku/src/index.ts | 22 ---- plugins/husky-npm/src/index.ts | 19 +-- plugins/lint-staged-npm/index.js | 0 plugins/lint-staged-npm/src/index.ts | 27 ---- plugins/npm/src/index.ts | 27 ---- plugins/prettier/src/index.ts | 12 -- 14 files changed, 1 insertion(+), 341 deletions(-) create mode 100644 plugins/circleci-deploy/index.js delete mode 100644 plugins/circleci-deploy/src/index.ts delete mode 100644 plugins/circleci-deploy/test/index.test.ts create mode 100644 plugins/circleci-npm/index.js delete mode 100644 plugins/circleci-npm/src/index.ts delete mode 100644 plugins/circleci-npm/test/index.test.ts create mode 100644 plugins/lint-staged-npm/index.js delete mode 100644 plugins/lint-staged-npm/src/index.ts diff --git a/plugins/circleci-deploy/index.js b/plugins/circleci-deploy/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/circleci-deploy/src/index.ts b/plugins/circleci-deploy/src/index.ts deleted file mode 100644 index 50548ef15..000000000 --- a/plugins/circleci-deploy/src/index.ts +++ /dev/null @@ -1,144 +0,0 @@ -import CircleCiConfigHook, { - CircleCIStatePartial, - generateConfigWithJob -} from '@dotcom-tool-kit/circleci/lib/circleci-config' -import { TestCI } from '@dotcom-tool-kit/circleci/lib/index' -import { getOptions } from '@dotcom-tool-kit/options' -import { JobConfig } from '@dotcom-tool-kit/types/src/circleci' -import type { Logger } from 'winston' - -const getServerlessAdditionalFields = (logger: Logger): JobConfig => { - const serverlessOptions = getOptions('@dotcom-tool-kit/serverless') - const herokuOptions = getOptions('@dotcom-tool-kit/heroku') - - if (serverlessOptions && herokuOptions) { - logger.warn( - 'Tool Kit currently does not support managing Heroku and Serverless apps in the same project.' - ) - } - - if (!serverlessOptions?.awsAccountId || !serverlessOptions?.systemCode) { - return {} - } - - return { - 'aws-account-id': serverlessOptions.awsAccountId, - 'system-code': serverlessOptions.systemCode - } -} - -export class DeployReview extends CircleCiConfigHook { - static job = 'tool-kit/deploy-review' - // needs to be a getter so that we can lazily wait for the global options - // object to be assigned before getting values from it - get config(): CircleCIStatePartial { - // CircleCI config generator which will additionally optionally pass Serverless - // options as parameters to the orb job to enable OIDC authentication - const serverlessAdditionalsFields = getServerlessAdditionalFields(this.logger) - - return generateConfigWithJob({ - name: DeployReview.job, - addToNightly: true, - requires: ['tool-kit/setup', 'waiting-for-approval'], - splitIntoMatrix: false, - additionalFields: { filters: { branches: { ignore: 'main' } }, ...serverlessAdditionalsFields } - }) - } -} - -export class DeployStaging extends CircleCiConfigHook { - static job = 'tool-kit/deploy-staging' - get config(): CircleCIStatePartial { - return generateConfigWithJob({ - name: DeployStaging.job, - addToNightly: false, - requires: ['tool-kit/setup'], - splitIntoMatrix: false, - additionalFields: { filters: { branches: { only: 'main' } } } - }) - } -} - -export class TestReview extends CircleCiConfigHook { - static job = 'tool-kit/e2e-test-review' - - get config() { - const jobOptions = { - name: TestReview.job, - requires: [DeployReview.job], - addToNightly: false, - splitIntoMatrix: false - } - - // CircleCI config generator which will additionally optionally pass Serverless - // options as parameters to the orb job to enable OIDC authentication - const serverlessAdditionalsFields = getServerlessAdditionalFields(this.logger) - - const options = getOptions('@dotcom-tool-kit/circleci') - if (options?.cypressImage) { - return { - executors: { cypress: { docker: [{ image: options.cypressImage }] } }, - ...generateConfigWithJob({ - ...jobOptions, - additionalFields: { ...serverlessAdditionalsFields, executor: 'cypress' } - }) - } - } - return generateConfigWithJob({ ...jobOptions, additionalFields: serverlessAdditionalsFields }) - } -} - -export class TestStaging extends CircleCiConfigHook { - static job = 'tool-kit/e2e-test-staging' - - get config() { - const jobOptions = { - name: TestStaging.job, - requires: [DeployStaging.job], - addToNightly: false, - splitIntoMatrix: false - } - - const options = getOptions('@dotcom-tool-kit/circleci') - if (options?.cypressImage) { - return { - executors: { cypress: { docker: [{ image: options.cypressImage }] } }, - ...generateConfigWithJob({ - ...jobOptions, - additionalFields: { executor: 'cypress' } - }) - } - } - return generateConfigWithJob(jobOptions) - } -} - -export class DeployProduction extends CircleCiConfigHook { - static job = 'tool-kit/deploy-production' - get config(): CircleCIStatePartial { - // CircleCI config generator which will additionally optionally pass Serverless - // options as parameters to the orb job to enable OIDC authentication - const serverlessAdditionalsFields = getServerlessAdditionalFields(this.logger) - - return generateConfigWithJob({ - name: DeployProduction.job, - addToNightly: false, - requires: [TestStaging.job, TestCI.job], - splitIntoMatrix: false, - additionalFields: { - ...serverlessAdditionalsFields, - filters: { branches: { only: 'main' } } - } - }) - } -} - -export const hooks = { - 'deploy:review': DeployReview, - 'deploy:staging': DeployStaging, - 'test:review': TestReview, - 'teardown:review': TestReview, - 'test:staging': TestStaging, - 'teardown:staging': TestStaging, - 'deploy:production': DeployProduction -} diff --git a/plugins/circleci-deploy/test/index.test.ts b/plugins/circleci-deploy/test/index.test.ts deleted file mode 100644 index fc1fb9e62..000000000 --- a/plugins/circleci-deploy/test/index.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { describe, it, expect } from '@jest/globals' -import * as circleciDeploy from '../' - -describe('CircleCI-Deploy plugin', () => { - it('should define CI deployment hooks', () => { - expect(circleciDeploy.hooks).toEqual( - expect.objectContaining({ - 'deploy:review': expect.any(Function), - 'deploy:staging': expect.any(Function), - 'deploy:production': expect.any(Function), - 'teardown:review': expect.any(Function), - 'teardown:staging': expect.any(Function), - 'test:review': expect.any(Function), - 'test:staging': expect.any(Function) - }) - ) - }) -}) diff --git a/plugins/circleci-npm/index.js b/plugins/circleci-npm/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/circleci-npm/src/index.ts b/plugins/circleci-npm/src/index.ts deleted file mode 100644 index 639fcd3bd..000000000 --- a/plugins/circleci-npm/src/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -import CircleCiConfigHook, { generateConfigWithJob } from '@dotcom-tool-kit/circleci/lib/circleci-config' - -class PublishHook extends CircleCiConfigHook { - static job = 'tool-kit/publish-tag' - config = generateConfigWithJob({ - name: PublishHook.job, - requires: ['tool-kit/test'], - splitIntoMatrix: false, - addToNightly: false, - additionalFields: { - context: 'npm-publish-token', - filters: { - branches: { ignore: '/.*/' } - } - } - }) -} - -export const hooks = { - 'publish:tag': PublishHook -} diff --git a/plugins/circleci-npm/test/index.test.ts b/plugins/circleci-npm/test/index.test.ts deleted file mode 100644 index eeb843176..000000000 --- a/plugins/circleci-npm/test/index.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { describe, it, expect } from '@jest/globals' -import { hooks } from '../' - -describe('npm plugin', () => { - it('should define package.json hooks', () => { - expect(hooks).toEqual( - expect.objectContaining({ - 'publish:tag': expect.any(Function) - }) - ) - }) -}) diff --git a/plugins/circleci/src/index.ts b/plugins/circleci/src/index.ts index 9f15c88f7..ce61f4528 100644 --- a/plugins/circleci/src/index.ts +++ b/plugins/circleci/src/index.ts @@ -1,34 +1,4 @@ import { writeState } from '@dotcom-tool-kit/state' -import CircleCiConfigHook, { generateConfigWithJob } from './circleci-config' - -export class BuildCI extends CircleCiConfigHook { - static job = 'tool-kit/build' - get config() { - return generateConfigWithJob({ - name: BuildCI.job, - requires: ['tool-kit/setup'], - splitIntoMatrix: true, - addToNightly: true - }) - } -} - -export class TestCI extends CircleCiConfigHook { - static job = 'tool-kit/test' - get config() { - return generateConfigWithJob({ - name: TestCI.job, - requires: [BuildCI.job], - splitIntoMatrix: true, - addToNightly: true - }) - } -} - -export const hooks = { - 'build:ci': BuildCI, - 'test:ci': TestCI -} const envVars = { branch: process.env.CIRCLE_BRANCH, diff --git a/plugins/cypress/src/index.ts b/plugins/cypress/src/index.ts index eefb1970d..ff56935e3 100644 --- a/plugins/cypress/src/index.ts +++ b/plugins/cypress/src/index.ts @@ -1,13 +1,3 @@ -import { PackageJsonHook } from '@dotcom-tool-kit/package-json-hook' import { CypressLocal, CypressCi } from './tasks/cypress' -class E2ETestHook extends PackageJsonHook { - key = 'e2e-test' - hook = 'e2e:local' -} - -export const hooks = { - 'e2e:local': E2ETestHook -} - export const tasks = { CypressLocal, CypressCi } diff --git a/plugins/heroku/src/index.ts b/plugins/heroku/src/index.ts index e818a2c0f..8caaef3d4 100644 --- a/plugins/heroku/src/index.ts +++ b/plugins/heroku/src/index.ts @@ -2,27 +2,5 @@ import HerokuProduction from './tasks/production' import HerokuStaging from './tasks/staging' import HerokuReview from './tasks/review' import HerokuTeardown from './tasks/teardown' -import { PackageJsonScriptHook } from '@dotcom-tool-kit/package-json-hook' - -class BuildRemote extends PackageJsonScriptHook { - key = 'heroku-postbuild' - hook = 'build:remote' -} - -class CleanupRemote extends PackageJsonScriptHook { - key = 'heroku-postbuild' - hook = 'cleanup:remote' -} - -class ReleaseRemote extends PackageJsonScriptHook { - key = 'heroku-postbuild' - hook = 'release:remote' -} - -export const hooks = { - 'cleanup:remote': CleanupRemote, - 'release:remote': ReleaseRemote, - 'build:remote': BuildRemote -} export const tasks = { HerokuProduction, HerokuStaging, HerokuReview, HerokuTeardown } diff --git a/plugins/husky-npm/src/index.ts b/plugins/husky-npm/src/index.ts index 96ae851a8..43ef84c5e 100644 --- a/plugins/husky-npm/src/index.ts +++ b/plugins/husky-npm/src/index.ts @@ -1,18 +1 @@ -import { HuskyHook } from './husky-hook' - -class GitPrecommit extends HuskyHook { - key = 'pre-commit' - hook = 'git:precommit' -} - -class GitCommitmsg extends HuskyHook { - key = 'commit-msg' - hook = 'git:commitmsg' -} - -export { HuskyHook } - -export const hooks = { - 'git:precommit': GitPrecommit, - 'git:commitmsg': GitCommitmsg -} +export { HuskyHook } from './husky-hook' diff --git a/plugins/lint-staged-npm/index.js b/plugins/lint-staged-npm/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/lint-staged-npm/src/index.ts b/plugins/lint-staged-npm/src/index.ts deleted file mode 100644 index 7b4ccbee2..000000000 --- a/plugins/lint-staged-npm/src/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { LintStagedHook } from '@dotcom-tool-kit/lint-staged' -import { getOptions } from '@dotcom-tool-kit/options' - -class TestStaged extends LintStagedHook { - static description = 'test git staged files' - - _key?: string - get key(): string { - return (this._key ??= getOptions('@dotcom-tool-kit/lint-staged-npm')?.testGlob ?? '**/*.js') - } - hook = 'test:staged' -} - -class FormatStaged extends LintStagedHook { - static description = 'format git staged files' - - _key?: string - get key(): string { - return (this._key ??= getOptions('@dotcom-tool-kit/lint-staged-npm')?.formatGlob ?? '**/*.js') - } - hook = 'format:staged' -} - -export const hooks = { - 'test:staged': TestStaged, - 'format:staged': FormatStaged -} diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts index d77712f2e..8e432f321 100644 --- a/plugins/npm/src/index.ts +++ b/plugins/npm/src/index.ts @@ -2,35 +2,8 @@ import { PackageJsonScriptHook } from '@dotcom-tool-kit/package-json-hook' import NpmPrune from './tasks/npm-prune' import NpmPublish from './tasks/npm-publish' -class BuildLocal extends PackageJsonScriptHook { - static description = 'hook for `npm run build`, for building an app locally' - - key = 'build' - hook = 'build:local' -} - -class TestLocal extends PackageJsonScriptHook { - static description = 'hook for `npm run test`, for running tests locally' - - key = 'test' - hook = 'test:local' -} - -class RunLocal extends PackageJsonScriptHook { - static description = 'hook for `npm start`, for running your app locally' - - key = 'start' - hook = 'run:local' -} - export { PackageJsonScriptHook as PackageJsonScriptHook } -export const hooks = { - 'build:local': BuildLocal, - 'test:local': TestLocal, - 'run:local': RunLocal -} - export const tasks = { NpmPrune, NpmPublish diff --git a/plugins/prettier/src/index.ts b/plugins/prettier/src/index.ts index 41e6fe25e..165bad0c8 100644 --- a/plugins/prettier/src/index.ts +++ b/plugins/prettier/src/index.ts @@ -1,15 +1,3 @@ -import { PackageJsonScriptHook } from '@dotcom-tool-kit/package-json-hook' import Prettier from './tasks/prettier' export const tasks = { Prettier } - -class FormatLocal extends PackageJsonScriptHook { - static description = 'format prettier' - - key = 'format' - hook = `format:local` -} - -export const hooks = { - 'format:local': FormatLocal -} From db98c71cf35b8cace3c701ea9c2bafbae0254463 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 13 Oct 2023 17:59:30 +0100 Subject: [PATCH 023/321] chore: remove most `installs:` stanzas from toolkitrcs that don't have hook base classes --- plugins/circleci-deploy/.toolkitrc.yml | 8 -------- plugins/circleci-npm/.toolkitrc.yml | 3 --- plugins/cypress/.toolkitrc.yml | 3 --- plugins/heroku/.toolkitrc.yml | 5 ----- plugins/husky-npm/.toolkitrc.yml | 3 --- plugins/lint-staged-npm/.toolkitrc.yml | 4 ---- plugins/npm/.toolkitrc.yml | 5 ----- plugins/prettier/.toolkitrc.yml | 3 --- 8 files changed, 34 deletions(-) diff --git a/plugins/circleci-deploy/.toolkitrc.yml b/plugins/circleci-deploy/.toolkitrc.yml index 76ba0bafa..067c53577 100644 --- a/plugins/circleci-deploy/.toolkitrc.yml +++ b/plugins/circleci-deploy/.toolkitrc.yml @@ -1,10 +1,2 @@ plugins: - '@dotcom-tool-kit/circleci' - -installs: - - 'deploy:review' - - 'deploy:staging' - - 'test:review' - - 'test:staging' - - 'teardown:staging' - - 'deploy:production' diff --git a/plugins/circleci-npm/.toolkitrc.yml b/plugins/circleci-npm/.toolkitrc.yml index 24cdc42df..9483399bc 100644 --- a/plugins/circleci-npm/.toolkitrc.yml +++ b/plugins/circleci-npm/.toolkitrc.yml @@ -2,8 +2,5 @@ plugins: - '@dotcom-tool-kit/circleci' - '@dotcom-tool-kit/npm' -installs: - - 'publish:tag' - commands: 'publish:tag': NpmPublish diff --git a/plugins/cypress/.toolkitrc.yml b/plugins/cypress/.toolkitrc.yml index cc5b99b32..31e51dc93 100644 --- a/plugins/cypress/.toolkitrc.yml +++ b/plugins/cypress/.toolkitrc.yml @@ -1,6 +1,3 @@ -installs: - - 'e2e:local' - tasks: - CypressCi - CypressLocal diff --git a/plugins/heroku/.toolkitrc.yml b/plugins/heroku/.toolkitrc.yml index 7dcaeaf06..0e5cb4a2f 100644 --- a/plugins/heroku/.toolkitrc.yml +++ b/plugins/heroku/.toolkitrc.yml @@ -2,11 +2,6 @@ plugins: - '@dotcom-tool-kit/npm' - '@dotcom-tool-kit/doppler' # required so the create script knows we need its options -installs: - - 'cleanup:remote' - - 'release:remote' - - 'build:remote' - tasks: - HerokuProduction - HerokuStaging diff --git a/plugins/husky-npm/.toolkitrc.yml b/plugins/husky-npm/.toolkitrc.yml index cfcdf6196..e69de29bb 100644 --- a/plugins/husky-npm/.toolkitrc.yml +++ b/plugins/husky-npm/.toolkitrc.yml @@ -1,3 +0,0 @@ -installs: - - 'git:precommit' - - 'git:commitmsg' diff --git a/plugins/lint-staged-npm/.toolkitrc.yml b/plugins/lint-staged-npm/.toolkitrc.yml index 29f671413..03647dfa9 100644 --- a/plugins/lint-staged-npm/.toolkitrc.yml +++ b/plugins/lint-staged-npm/.toolkitrc.yml @@ -1,7 +1,3 @@ plugins: - '@dotcom-tool-kit/lint-staged' - '@dotcom-tool-kit/husky-npm' - -installs: - - 'test:staged' - - 'format:staged' diff --git a/plugins/npm/.toolkitrc.yml b/plugins/npm/.toolkitrc.yml index 856096a25..2277d7455 100644 --- a/plugins/npm/.toolkitrc.yml +++ b/plugins/npm/.toolkitrc.yml @@ -1,8 +1,3 @@ -installs: - - 'build:local' - - 'test:local' - - 'run:local' - tasks: - NpmPrune - NpmPublish diff --git a/plugins/prettier/.toolkitrc.yml b/plugins/prettier/.toolkitrc.yml index 45168b2be..7434c75c5 100644 --- a/plugins/prettier/.toolkitrc.yml +++ b/plugins/prettier/.toolkitrc.yml @@ -1,6 +1,3 @@ -installs: - - 'format:local' - tasks: - Prettier From 829c747465ca23354c86cdb93a1de02b287b5eaf Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 11:59:39 +0000 Subject: [PATCH 024/321] test: remove tests for exported hooks --- plugins/heroku/test/index.test.ts | 13 ------------- plugins/npm/test/index.test.ts | 14 -------------- 2 files changed, 27 deletions(-) delete mode 100644 plugins/heroku/test/index.test.ts delete mode 100644 plugins/npm/test/index.test.ts diff --git a/plugins/heroku/test/index.test.ts b/plugins/heroku/test/index.test.ts deleted file mode 100644 index cf315f70d..000000000 --- a/plugins/heroku/test/index.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { describe, it, expect } from '@jest/globals' -import * as heroku from '../' - -describe('Heroku plugin', () => { - it('should define Heroku build hooks', () => { - expect(heroku.hooks).toEqual( - expect.objectContaining({ - 'build:remote': expect.any(Function), - 'release:remote': expect.any(Function) - }) - ) - }) -}) diff --git a/plugins/npm/test/index.test.ts b/plugins/npm/test/index.test.ts deleted file mode 100644 index a238b7e35..000000000 --- a/plugins/npm/test/index.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { describe, it, expect } from '@jest/globals' -import * as npm from '../' - -describe('npm plugin', () => { - it('should define package.json hooks', () => { - expect(npm.hooks).toEqual( - expect.objectContaining({ - 'build:local': expect.any(Function), - 'test:local': expect.any(Function), - 'run:local': expect.any(Function) - }) - ) - }) -}) From 124f0fea3fc2bc2a05582e57455839f3f801d027 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 20 Nov 2023 15:52:32 +0000 Subject: [PATCH 025/321] test: fix constructor arguments for tasks in tests --- lib/package-json-hook/test/index.test.ts | 12 +++++----- plugins/circleci/test/circleci-config.test.ts | 24 +++++++++---------- plugins/heroku/test/tasks/teardown.test.ts | 6 ++--- plugins/npm/test/npm-publish.test.ts | 14 +++++------ .../test/tasks/upload-assets-to-s3.test.ts | 7 +----- 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/lib/package-json-hook/test/index.test.ts b/lib/package-json-hook/test/index.test.ts index b88ffca9e..9d187c4f7 100644 --- a/lib/package-json-hook/test/index.test.ts +++ b/lib/package-json-hook/test/index.test.ts @@ -22,21 +22,21 @@ describe('package.json hook', () => { describe('check', () => { it('should return true when package.json has hook call in script', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') expect(await hook.check()).toBeTruthy() }) it('should return true when script includes other hooks', async () => { process.chdir(path.join(__dirname, 'files', 'multiple-hooks')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') expect(await hook.check()).toBeTruthy() }) it(`should return false when package.json doesn't have hook call in script`, async () => { process.chdir(path.join(__dirname, 'files', 'without-hook')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') expect(await hook.check()).toBeFalsy() }) @@ -52,7 +52,7 @@ describe('package.json hook', () => { process.chdir(base) try { - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') const state = await hook.install() await hook.commitInstall(state) @@ -77,7 +77,7 @@ describe('package.json hook', () => { trailingString = '--' } - const hook = new TestAppendHook(logger) + const hook = new TestAppendHook(logger, 'TestAppendHook') const state = await hook.install() await hook.commitInstall(state) @@ -102,7 +102,7 @@ describe('package.json hook', () => { field = ['scripts', 'nested'] } - const hook = new TestNestedHook(logger) + const hook = new TestNestedHook(logger, 'TestNestedHook') const state = await hook.install() await hook.commitInstall(state) diff --git a/plugins/circleci/test/circleci-config.test.ts b/plugins/circleci/test/circleci-config.test.ts index a194c60b1..f64da6c30 100644 --- a/plugins/circleci/test/circleci-config.test.ts +++ b/plugins/circleci/test/circleci-config.test.ts @@ -55,19 +55,19 @@ describe('CircleCI config hook', () => { describe('check', () => { it('should return true if the hook job is in the circleci workflow', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') expect(await hook.check()).toBeTruthy() }) it('should return false if the hook job is not in the circleci workflow', async () => { process.chdir(path.join(__dirname, 'files', 'without-hook')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') expect(await hook.check()).toBeFalsy() }) it('should return false if the base configuration is missing', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') // reset field overridden by FakeCircleCiConfigHook so that we do check // for the base config hook.haveCheckedBaseConfig = false @@ -78,7 +78,7 @@ describe('CircleCI config hook', () => { describe('install', () => { it("should throw an error explaining how to autogenerate config if existing config file doesn't contain any tool-kit jobs", async () => { process.chdir(path.join(__dirname, 'files', 'without-tool-kit')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') const state = await hook.install() await expect(hook.commitInstall(state)).rejects.toThrow( "Your project has an existing CircleCI config file which doesn't contain" @@ -87,7 +87,7 @@ describe('CircleCI config hook', () => { it('should throw an error explaining what to do if no autogenerated comment', async () => { process.chdir(path.join(__dirname, 'files', 'without-hook')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') const state = await hook.install() await expect(hook.commitInstall(state)).rejects.toThrow( 'Your CircleCI configuration is missing the expected fields from Tool Kit:' @@ -97,7 +97,7 @@ describe('CircleCI config hook', () => { it("should add a job with its jobConfig to a file with a comment if it's not there", async () => { process.chdir(path.join(__dirname, 'files', 'comment-without-hook')) - const hook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') const state = await hook.install() await hook.commitInstall(state) @@ -131,8 +131,8 @@ describe('CircleCI config hook', () => { it('should merge jobs from two hooks', async () => { process.chdir(path.join(__dirname, 'files', 'comment-without-hook')) - const hook = new TestHook(logger) - const anotherHook = new TestAnotherHook(logger) + const hook = new TestHook(logger, 'TestHook') + const anotherHook = new TestAnotherHook(logger, 'TestAnotherHook') let state = await hook.install() state = await anotherHook.install(state) await hook.commitInstall(state) @@ -172,8 +172,8 @@ describe('CircleCI config hook', () => { it('should discard job from duplicate hook', async () => { process.chdir(path.join(__dirname, 'files', 'comment-without-hook')) - const hook = new TestHook(logger) - const sameHook = new TestHook(logger) + const hook = new TestHook(logger, 'TestHook') + const sameHook = new TestHook(logger, 'TestHook') let state = await hook.install() state = await sameHook.install(state) await hook.commitInstall(state) @@ -195,8 +195,8 @@ describe('CircleCI config hook', () => { it('correctly generates a new configuration file', async () => { process.chdir(path.join(__dirname, 'files', 'comment-without-hook')) - const hook = new TestHook(logger) - const anotherHook = new TestAnotherHook(logger) + const hook = new TestHook(logger, 'TestHook') + const anotherHook = new TestAnotherHook(logger, 'TestAnotherHook') let state = await hook.install() state = await anotherHook.install(state) await hook.commitInstall(state) diff --git a/plugins/heroku/test/tasks/teardown.test.ts b/plugins/heroku/test/tasks/teardown.test.ts index f4e7d2d5d..3946aa9ab 100644 --- a/plugins/heroku/test/tasks/teardown.test.ts +++ b/plugins/heroku/test/tasks/teardown.test.ts @@ -18,7 +18,7 @@ const mockScaleDyno = jest.spyOn(utils, 'scaleDyno') describe('teardown', () => { it('should call scaleDyno with app name', async () => { mockScaleDyno.mockImplementationOnce(() => Promise.resolve()) - const task = new Teardown(logger, {}) + const task = new Teardown(logger, 'HerokuTeardown', {}) await task.run() expect(utils.scaleDyno).toHaveBeenCalledWith(expect.anything(), appName, 0) @@ -26,13 +26,13 @@ describe('teardown', () => { it('should resolve if succesfully completed', async () => { mockScaleDyno.mockImplementationOnce(() => Promise.resolve()) - const task = new Teardown(logger, {}) + const task = new Teardown(logger, 'HerokuTeardown', {}) await expect(task.run()).resolves.not.toThrow() }) it('should return a rejected promise if it completes unsuccessfully', async () => { mockScaleDyno.mockImplementationOnce(() => Promise.reject()) - const task = new Teardown(logger, {}) + const task = new Teardown(logger, 'HerokuTeardown', {}) await expect(task.run()).rejects.toThrowError() }) }) diff --git a/plugins/npm/test/npm-publish.test.ts b/plugins/npm/test/npm-publish.test.ts index b4950a052..bb33fe557 100644 --- a/plugins/npm/test/npm-publish.test.ts +++ b/plugins/npm/test/npm-publish.test.ts @@ -35,7 +35,7 @@ describe('NpmPublish', () => { it('should throw an error if ci is not found in state', async () => { readStateMock.mockReturnValue(null) - const task = new NpmPublish(logger, {}) + const task = new NpmPublish(logger, 'NpmPublish', {}) await expect(async () => { await task.run() }).rejects.toThrow( @@ -46,7 +46,7 @@ describe('NpmPublish', () => { it('should throw error if tag is not found', async () => { readStateMock.mockReturnValue({ tag: '', repo: '', branch: '', version: '' }) - const task = new NpmPublish(logger, {}) + const task = new NpmPublish(logger, 'NpmPublish', {}) await expect(async () => { await task.run() }).rejects.toThrow( @@ -57,19 +57,19 @@ describe('NpmPublish', () => { }) it('should return prerelease if match prerelease regex in getNpmTag', () => { - const task = new NpmPublish(logger, {}) + const task = new NpmPublish(logger, 'NpmPublish', {}) expect(task.getNpmTag('v1.6.0-beta.1')).toEqual('prerelease') }) it('should return latest if match latest regex in getNpmTag', () => { - const task = new NpmPublish(logger, {}) + const task = new NpmPublish(logger, 'NpmPublish', {}) expect(task.getNpmTag('v1.6.0')).toEqual('latest') }) it('should throw error if tag does not match semver regex', async () => { readStateMock.mockReturnValue({ tag: 'random-branch', repo: '', branch: '', version: '' }) - const task = new NpmPublish(logger, {}) + const task = new NpmPublish(logger, 'NpmPublish', {}) await expect(async () => { await task.run() }).rejects.toThrow( @@ -85,7 +85,7 @@ describe('NpmPublish', () => { const listPackedFilesSpy = jest.spyOn(NpmPublish.prototype, 'listPackedFiles') listPackedFilesSpy.mockImplementation(() => Promise.resolve()) - const task = new NpmPublish(logger, {}) + const task = new NpmPublish(logger, 'NpmPublish', {}) await task.run() expect(listPackedFilesSpy).toBeCalled() @@ -98,7 +98,7 @@ describe('NpmPublish', () => { process.env.NPM_AUTH_TOKEN = process.env.NPM_AUTH_TOKEN || 'dummy_value' readStateMock.mockReturnValue({ tag: MOCK_CIRCLE_TAG, repo: '', branch: '', version: '' }) - const task = new NpmPublish(logger, {}) + const task = new NpmPublish(logger, 'NpmPublish', {}) await task.run() expect(writeFile).toHaveBeenCalledWith( diff --git a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts index 6acc1985d..aaa1c5ba8 100644 --- a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts +++ b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts @@ -98,12 +98,7 @@ describe('upload-assets-to-s3', () => { directory: testDirectory }) - expect.assertions(1) - try { - await task.run() - } catch (e) { - expect(e.details).toEqual(mockError) - } + await expect(task.run()).rejects.toThrow(mockError) }) // HACK:20231006:IM make sure hack to support Doppler migration works From c8b7396ea32218c1a28ff49129a75ab4a54b8f72 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 21 Nov 2023 10:48:10 +0000 Subject: [PATCH 026/321] test: don't override ts-jest settings in packages --- core/cli/jest.config.js | 9 ++++++++- plugins/n-test/jest.config.js | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/cli/jest.config.js b/core/cli/jest.config.js index e549b3a36..9a09e57a1 100644 --- a/core/cli/jest.config.js +++ b/core/cli/jest.config.js @@ -2,5 +2,12 @@ const base = require('../../jest.config.base') module.exports = { ...base, - globals: { 'ts-jest': { tsconfig: { resolveJsonModule: true } } } + globals: { + 'ts-jest': { + tsconfig: { + ...base.globals['ts-jest'].tsconfig, + resolveJsonModule: true + } + } + } } diff --git a/plugins/n-test/jest.config.js b/plugins/n-test/jest.config.js index e621b81cb..ebfc1c86b 100644 --- a/plugins/n-test/jest.config.js +++ b/plugins/n-test/jest.config.js @@ -5,6 +5,7 @@ module.exports = { globals: { 'ts-jest': { tsconfig: { + ...base.globals['ts-jest'].tsconfig, paths: { puppeteer: ['__mocks__/puppeteer'] } From 44ab9ae2a64bec4a4a23b1a5aea03cbf621b2c9e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 21 Nov 2023 11:28:18 +0000 Subject: [PATCH 027/321] test: use test-specific tsconfig files instead of inline ts-jest compiler options --- core/cli/jest.config.js | 7 +++---- core/cli/tsconfig.test.json | 6 ++++++ plugins/n-test/jest.config.js | 9 +++------ plugins/n-test/tsconfig.test.json | 8 ++++++++ 4 files changed, 20 insertions(+), 10 deletions(-) create mode 100644 core/cli/tsconfig.test.json create mode 100644 plugins/n-test/tsconfig.test.json diff --git a/core/cli/jest.config.js b/core/cli/jest.config.js index 9a09e57a1..270a20916 100644 --- a/core/cli/jest.config.js +++ b/core/cli/jest.config.js @@ -1,13 +1,12 @@ const base = require('../../jest.config.base') +const path = require('path') module.exports = { ...base, globals: { 'ts-jest': { - tsconfig: { - ...base.globals['ts-jest'].tsconfig, - resolveJsonModule: true - } + ...base.globals['ts-jest'], + tsconfig: path.resolve(__dirname, './tsconfig.test.json') } } } diff --git a/core/cli/tsconfig.test.json b/core/cli/tsconfig.test.json new file mode 100644 index 000000000..1664c1a55 --- /dev/null +++ b/core/cli/tsconfig.test.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.settings.json", + "compilerOptions": { + "resolveJsonModule": true + } +} diff --git a/plugins/n-test/jest.config.js b/plugins/n-test/jest.config.js index ebfc1c86b..270a20916 100644 --- a/plugins/n-test/jest.config.js +++ b/plugins/n-test/jest.config.js @@ -1,15 +1,12 @@ const base = require('../../jest.config.base') +const path = require('path') module.exports = { ...base, globals: { 'ts-jest': { - tsconfig: { - ...base.globals['ts-jest'].tsconfig, - paths: { - puppeteer: ['__mocks__/puppeteer'] - } - } + ...base.globals['ts-jest'], + tsconfig: path.resolve(__dirname, './tsconfig.test.json') } } } diff --git a/plugins/n-test/tsconfig.test.json b/plugins/n-test/tsconfig.test.json new file mode 100644 index 000000000..b479ffc0f --- /dev/null +++ b/plugins/n-test/tsconfig.test.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.settings.json", + "compilerOptions": { + "paths": { + "puppeteer": ["__mocks__/puppeteer"] + } + } +} From b2f63e4bdfb37a366c7df528fda750c204547bde Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 21 Nov 2023 11:45:04 +0000 Subject: [PATCH 028/321] test: expect wrapped error message in upload-assets-to-s3 test --- .../upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts index aaa1c5ba8..d17f57175 100644 --- a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts +++ b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts @@ -98,7 +98,7 @@ describe('upload-assets-to-s3', () => { directory: testDirectory }) - await expect(task.run()).rejects.toThrow(mockError) + await expect(task.run()).rejects.toThrow('ft-next-hashed-assets-prod failed') }) // HACK:20231006:IM make sure hack to support Doppler migration works From 400f3a4996bf0e0773914dc985945e0d058ba204 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 15 Nov 2023 11:14:30 +0000 Subject: [PATCH 029/321] refactor: pass entire entrypoint into import --- core/cli/src/config.ts | 4 ++-- core/cli/src/index.ts | 4 ++-- core/cli/src/plugin.ts | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index d6961645b..88e1065b7 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -5,7 +5,7 @@ import path from 'path' import type { Logger } from 'winston' import type { CommandTask } from './command' -import { RawPluginModule, importPlugin, loadPlugin, resolvePlugin, validatePluginHooks } from './plugin' +import { RawPluginModule, importEntryPoint, loadPlugin, resolvePlugin, validatePluginHooks } from './plugin' import { Conflict, findConflicts, withoutConflicts, isConflict, findConflictingEntries } from './conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' @@ -77,7 +77,7 @@ const coreRoot = path.resolve(__dirname, '../') export const loadHooks = async (logger: Logger, config: ValidConfig): Promise[]>> => { const hookResults = await Promise.all( Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { - const hookPlugin = await importPlugin(entryPoint.modulePath) + const hookPlugin = await importEntryPoint(entryPoint) return flatMapValidated(hookPlugin, (plugin) => { const pluginHooks = validatePluginHooks(plugin as RawPluginModule) diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 3d887bc49..dbc96437b 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -12,7 +12,7 @@ import { reduceValidated, unwrapValidated } from '@dotcom-tool-kit/types' -import { RawPluginModule, importPlugin, validatePluginTasks } from './plugin' +import { RawPluginModule, importEntryPoint, validatePluginTasks } from './plugin' type ErrorSummary = { hook: string @@ -44,7 +44,7 @@ const loadTasks = async ( const taskResults = await Promise.all( taskNames.map(async (taskName) => { const entryPoint = config.tasks[taskName] - const taskPlugin = await importPlugin(entryPoint.modulePath) + const taskPlugin = await importEntryPoint(entryPoint) return flatMapValidated(taskPlugin, (plugin) => { const pluginTasks = validatePluginTasks(plugin as RawPluginModule) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index e769eb08b..e70d5b513 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -89,10 +89,9 @@ export function validatePluginHooks(plugin: RawPluginModule): Validated> { +export async function importEntryPoint(entryPoint: EntryPoint): Promise> { try { - // pluginPath is an absolute resolved path to a plugin module as found from its parent - const pluginModule: unknown = await import(pluginPath) + const pluginModule: unknown = await import(entryPoint.modulePath) return { valid: true, value: pluginModule From c66ec83ab9ab9560b3e2835b559cada0e89b3020 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 09:46:18 +0000 Subject: [PATCH 030/321] feat!: make plugin loading even lazier by having separate entrypoints for each task and hook --- core/cli/src/config.ts | 12 ++-- core/cli/src/index.ts | 20 +++---- core/cli/src/plugin.ts | 122 ++++++++++++++++----------------------- core/cli/src/rc-file.ts | 6 +- core/create/src/index.ts | 4 +- lib/types/src/index.ts | 17 +----- 6 files changed, 72 insertions(+), 109 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 88e1065b7..db3058cbe 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -5,13 +5,13 @@ import path from 'path' import type { Logger } from 'winston' import type { CommandTask } from './command' -import { RawPluginModule, importEntryPoint, loadPlugin, resolvePlugin, validatePluginHooks } from './plugin' +import { importEntryPoint, loadPlugin, resolvePlugin } from './plugin' import { Conflict, findConflicts, withoutConflicts, isConflict, findConflictingEntries } from './conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' import { - flatMapValidated, Hook, + HookConstructor, mapValidated, Plugin, reduceValidated, @@ -77,13 +77,9 @@ const coreRoot = path.resolve(__dirname, '../') export const loadHooks = async (logger: Logger, config: ValidConfig): Promise[]>> => { const hookResults = await Promise.all( Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { - const hookPlugin = await importEntryPoint(entryPoint) + const hookResult = await importEntryPoint(Hook, entryPoint) - return flatMapValidated(hookPlugin, (plugin) => { - const pluginHooks = validatePluginHooks(plugin as RawPluginModule) - - return mapValidated(pluginHooks, (hooks) => new hooks[hookName](logger, hookName)) - }) + return mapValidated(hookResult, (Hook) => new ((Hook as unknown) as HookConstructor)(logger, hookName)) }) ) diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index dbc96437b..10dacdbcd 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -6,13 +6,13 @@ import type { Logger } from 'winston' import { formatPluginTree } from './messages' import { Task, + TaskConstructor, Validated, - flatMapValidated, mapValidated, reduceValidated, unwrapValidated } from '@dotcom-tool-kit/types' -import { RawPluginModule, importEntryPoint, validatePluginTasks } from './plugin' +import { importEntryPoint } from './plugin' type ErrorSummary = { hook: string @@ -44,16 +44,16 @@ const loadTasks = async ( const taskResults = await Promise.all( taskNames.map(async (taskName) => { const entryPoint = config.tasks[taskName] - const taskPlugin = await importEntryPoint(entryPoint) + const taskResult = await importEntryPoint(Task, entryPoint) - return flatMapValidated(taskPlugin, (plugin) => { - const pluginTasks = validatePluginTasks(plugin as RawPluginModule) - - return mapValidated(pluginTasks, (tasks) => [ + return mapValidated(taskResult, (Task) => [ + taskName, + new ((Task as unknown) as TaskConstructor)( + logger, taskName, - new tasks[taskName](logger, taskName, getOptions(entryPoint.plugin.id as OptionKey) ?? {}) - ]) - }) + getOptions(entryPoint.plugin.id as OptionKey) ?? {} + ) + ]) }) ) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index e70d5b513..f3c4bf3b9 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,12 +1,9 @@ import { styles as s } from '@dotcom-tool-kit/logger' import { - Hook, mapValidated, mapValidationError, Plugin, - PluginModule, reduceValidated, - Task, Valid, Validated } from '@dotcom-tool-kit/types' @@ -17,6 +14,7 @@ import { Conflict, isConflict } from './conflict' import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' import { isPlainObject } from 'lodash' +import { Base } from '@dotcom-tool-kit/types/src/base' function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { if (!possibleDescendent.parent) { @@ -30,80 +28,60 @@ function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boo const isPlainObjectGuard = (value: unknown): value is Record => isPlainObject(value) -export type RawPluginModule = Partial - -export function validatePluginTasks(plugin: RawPluginModule): Validated { - if (plugin.tasks) { - if (!isPlainObjectGuard(plugin.tasks)) { - return { - valid: false, - reasons: [`the exported ${s.code('tasks')} value from this plugin is not an object`] - } - } else { - return mapValidated( - reduceValidated( - Object.entries(plugin.tasks).map(([id, task]) => - mapValidationError( - mapValidated(Task.isCompatible(task), (task) => [id, task]), - (reasons) => [ - `the task ${s.task(task.name)} is not a compatible instance of ${s.code( - 'Task' - )}:\n - ${reasons.join('\n - ')}` - ] - ) - ) - ), - Object.fromEntries - ) - } - } - - return { valid: true, value: {} } -} - -export function validatePluginHooks(plugin: RawPluginModule): Validated { - if (plugin.hooks) { - if (!isPlainObjectGuard(plugin.hooks)) { - return { - valid: false, - reasons: [`the exported ${s.code('hooks')} value from this plugin is not an object`] - } - } else { - return mapValidated( - reduceValidated( - Object.entries(plugin.hooks).map(([id, hook]) => - mapValidationError( - mapValidated(Hook.isCompatible(hook), (hook) => [id, hook]), - (reasons) => [ - `the hook ${s.hook(id)} is not a compatible instance of ${s.code( - 'Hook' - )}:\n - ${reasons.join('\n - ')}` - ] - ) - ) - ), - Object.fromEntries - ) +// the subclasses of Base have different constructor signatures so we need to omit +// the constructor from the type bound here so you can actually pass in a subclass +export async function importEntryPoint>( + type: T, + entryPoint: EntryPoint +): Promise> { + let resolvedPath: string + try { + resolvedPath = resolveFrom(entryPoint.plugin.root, entryPoint.modulePath) + } catch (e) { + return { + valid: false, + reasons: [ + `could not find entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( + entryPoint.plugin.id + )}` + ] } } - return { valid: true, value: {} } -} -export async function importEntryPoint(entryPoint: EntryPoint): Promise> { + let pluginModule: unknown try { - const pluginModule: unknown = await import(entryPoint.modulePath) - return { - valid: true, - value: pluginModule - } + pluginModule = await import(resolvedPath) } catch (e) { const err = e as Error return { valid: false, reasons: [ - `an error was thrown when loading this plugin's entrypoint:\n ${s.code( - indentReasons(err.toString()) - )}` + `an error was thrown when loading entrypoint ${s.filepath( + entryPoint.modulePath + )} in plugin ${s.plugin(entryPoint.plugin.id)}:\n ${s.code(indentReasons(err.toString()))}` + ] + } + } + + if ( + isPlainObjectGuard(pluginModule) && + 'default' in pluginModule && + typeof pluginModule.default === 'function' + ) { + const name = pluginModule.default.name + + return mapValidationError(type.isCompatible(pluginModule.default), (reasons) => [ + `the ${type.name.toLowerCase()} ${s.hook(name)} is not a compatible instance of ${s.code( + type.name + )}:\n - ${reasons.join('\n - ')}` + ]) + } else { + return { + valid: false, + reasons: [ + `entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( + entryPoint.plugin.id + )} does not have a ${s.code('default')} export` ] } } @@ -180,11 +158,11 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger if (plugin.rcFile) { // add plugin tasks to our task registry, handling any conflicts - for (const taskName of plugin.rcFile.tasks || []) { + for (const [taskName, modulePath] of Object.entries(plugin.rcFile.tasks || {})) { const existingTaskId = config.tasks[taskName] const entryPoint: EntryPoint = { plugin, - modulePath: plugin.id + modulePath } if (existingTaskId) { @@ -201,11 +179,11 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger // add hooks to the registry, handling any conflicts // TODO refactor with command conflict handler - for (const hookName of plugin.rcFile.installs || []) { + for (const [hookName, modulePath] of Object.entries(plugin.rcFile.installs || {})) { const existingHookId = config.hooks[hookName] const entryPoint: EntryPoint = { plugin, - modulePath: plugin.id + modulePath } if (existingHookId) { diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 202f2fdd4..037ef20e3 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -5,7 +5,7 @@ import * as path from 'path' import type { Logger } from 'winston' export const explorer = cosmiconfig('toolkit', { ignoreEmptySearchPlaces: false }) -const emptyConfig = { plugins: [], installs: [], tasks: [], commands: {}, options: {} } +const emptyConfig = { plugins: [], installs: {}, tasks: {}, commands: {}, options: {} } let rootConfig: string | undefined type RawRCFile = { @@ -35,8 +35,8 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo const config: RawRCFile = result.config return { plugins: config.plugins ?? [], - installs: config.installs ?? [], - tasks: config.tasks ?? [], + installs: config.installs ?? {}, + tasks: config.tasks ?? {}, commands: config.commands ?? {}, options: config.options ?? {} } diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 5739f3db6..4dcadbfcd 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -113,8 +113,8 @@ async function executeMigration( async function main() { const toolKitConfig: RCFile = { plugins: [], - installs: [], - tasks: [], + installs: {}, + tasks: {}, commands: {}, options: {} } diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 238adefba..409fa890d 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -1,14 +1,12 @@ -import type { HookConstructor } from './hook' -import type { TaskConstructor } from './task' - export * from './validated' +export * from './base' export * from './task' export * from './hook' export type RCFile = { plugins: string[] - installs: string[] - tasks: string[] + installs: { [id: string]: string } + tasks: { [id: string]: string } commands: { [id: string]: string | string[] } options: { [id: string]: Record } } @@ -20,12 +18,3 @@ export interface Plugin { parent?: Plugin children?: Plugin[] } - -export interface PluginModule { - tasks: { - [id: string]: TaskConstructor - } - hooks: { - [id: string]: HookConstructor - } -} From 713e8d36343ccabfeb289da67a54cb211f29b52f Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 14:58:37 +0000 Subject: [PATCH 031/321] chore: put all task entrypoints into plugin toolkitrcs --- plugins/babel/.toolkitrc.yml | 4 ++-- plugins/babel/package.json | 1 - plugins/babel/src/index.ts | 4 ---- plugins/circleci/.toolkitrc.yml | 3 --- plugins/cypress/.toolkitrc.yml | 4 ++-- plugins/cypress/src/index.ts | 3 --- plugins/cypress/src/tasks/ci.ts | 23 +++++++++++++++++++ .../src/tasks/{cypress.ts => local.ts} | 20 +--------------- plugins/eslint/.toolkitrc.yml | 2 +- plugins/eslint/src/index.ts | 3 --- plugins/heroku/.toolkitrc.yml | 8 +++---- plugins/heroku/src/index.ts | 6 ----- plugins/jest/.toolkitrc.yml | 4 ++-- plugins/jest/src/index.ts | 7 ------ plugins/lint-staged/.toolkitrc.yml | 2 +- plugins/lint-staged/src/hook.ts | 6 ----- plugins/lint-staged/src/index.ts | 4 ---- plugins/mocha/.toolkitrc.yml | 2 +- plugins/mocha/src/index.ts | 3 --- plugins/n-test/.toolkitrc.yml | 2 +- plugins/n-test/src/index.ts | 3 --- plugins/next-router/.toolkitrc.yml | 2 +- plugins/next-router/src/index.ts | 3 --- plugins/node/.toolkitrc.yml | 2 +- plugins/node/src/index.ts | 3 --- plugins/nodemon/.toolkitrc.yml | 2 +- plugins/nodemon/src/index.ts | 3 --- plugins/npm/.toolkitrc.yml | 4 ++-- plugins/npm/src/index.ts | 11 +-------- .../npm/src/tasks/{npm-prune.ts => prune.ts} | 0 .../src/tasks/{npm-publish.ts => publish.ts} | 0 plugins/pa11y/.toolkitrc.yml | 2 +- plugins/pa11y/src/index.ts | 3 --- plugins/prettier/.toolkitrc.yml | 2 +- plugins/prettier/src/index.ts | 3 --- plugins/serverless/.toolkitrc.yml | 6 ++--- plugins/serverless/src/index.ts | 6 ----- plugins/typescript/.toolkitrc.yml | 6 ++--- plugins/typescript/src/index.ts | 3 --- plugins/typescript/src/tasks/build.ts | 7 ++++++ plugins/typescript/src/tasks/test.ts | 7 ++++++ plugins/typescript/src/tasks/typescript.ts | 20 +--------------- plugins/typescript/src/tasks/watch.ts | 7 ++++++ plugins/upload-assets-to-s3/.toolkitrc.yml | 2 +- plugins/upload-assets-to-s3/src/index.ts | 3 --- plugins/webpack/.toolkitrc.yml | 6 ++--- plugins/webpack/src/index.ts | 5 ---- 47 files changed, 78 insertions(+), 154 deletions(-) delete mode 100644 plugins/babel/src/index.ts create mode 100644 plugins/cypress/src/tasks/ci.ts rename plugins/cypress/src/tasks/{cypress.ts => local.ts} (54%) delete mode 100644 plugins/eslint/src/index.ts delete mode 100644 plugins/heroku/src/index.ts delete mode 100644 plugins/jest/src/index.ts delete mode 100644 plugins/lint-staged/src/hook.ts delete mode 100644 plugins/lint-staged/src/index.ts delete mode 100644 plugins/mocha/src/index.ts delete mode 100644 plugins/n-test/src/index.ts delete mode 100644 plugins/next-router/src/index.ts delete mode 100644 plugins/node/src/index.ts delete mode 100644 plugins/nodemon/src/index.ts rename plugins/npm/src/tasks/{npm-prune.ts => prune.ts} (100%) rename plugins/npm/src/tasks/{npm-publish.ts => publish.ts} (100%) delete mode 100644 plugins/pa11y/src/index.ts delete mode 100644 plugins/prettier/src/index.ts delete mode 100644 plugins/serverless/src/index.ts delete mode 100644 plugins/typescript/src/index.ts create mode 100644 plugins/typescript/src/tasks/build.ts create mode 100644 plugins/typescript/src/tasks/test.ts create mode 100644 plugins/typescript/src/tasks/watch.ts delete mode 100644 plugins/upload-assets-to-s3/src/index.ts delete mode 100644 plugins/webpack/src/index.ts diff --git a/plugins/babel/.toolkitrc.yml b/plugins/babel/.toolkitrc.yml index 5da99994d..cd4388afc 100644 --- a/plugins/babel/.toolkitrc.yml +++ b/plugins/babel/.toolkitrc.yml @@ -1,6 +1,6 @@ tasks: - - BabelDevelopment - - BabelProduction + BabelDevelopment: './lib/tasks/development' + BabelProduction: './lib/tasks/production' commands: 'build:local': BabelDevelopment diff --git a/plugins/babel/package.json b/plugins/babel/package.json index 6e06aeacb..093022e62 100644 --- a/plugins/babel/package.json +++ b/plugins/babel/package.json @@ -1,7 +1,6 @@ { "name": "@dotcom-tool-kit/babel", "version": "3.2.0", - "main": "lib", "description": "", "author": "FT.com Platforms Team ", "license": "MIT", diff --git a/plugins/babel/src/index.ts b/plugins/babel/src/index.ts deleted file mode 100644 index c7a2f07eb..000000000 --- a/plugins/babel/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import BabelDevelopment from './tasks/development' -import BabelProduction from './tasks/production' - -export const tasks = { BabelDevelopment, BabelProduction } diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index 93d8bc9c8..e69de29bb 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -1,3 +0,0 @@ -installs: - - 'build:ci' - - 'test:ci' diff --git a/plugins/cypress/.toolkitrc.yml b/plugins/cypress/.toolkitrc.yml index 31e51dc93..92cd32fbe 100644 --- a/plugins/cypress/.toolkitrc.yml +++ b/plugins/cypress/.toolkitrc.yml @@ -1,6 +1,6 @@ tasks: - - CypressCi - - CypressLocal + CypressCi: './lib/tasks/ci' + CypressLocal: './lib/tasks/local' commands: 'test:review': CypressCi diff --git a/plugins/cypress/src/index.ts b/plugins/cypress/src/index.ts index ff56935e3..e69de29bb 100644 --- a/plugins/cypress/src/index.ts +++ b/plugins/cypress/src/index.ts @@ -1,3 +0,0 @@ -import { CypressLocal, CypressCi } from './tasks/cypress' - -export const tasks = { CypressLocal, CypressCi } diff --git a/plugins/cypress/src/tasks/ci.ts b/plugins/cypress/src/tasks/ci.ts new file mode 100644 index 000000000..3ce667389 --- /dev/null +++ b/plugins/cypress/src/tasks/ci.ts @@ -0,0 +1,23 @@ +import { spawn } from 'child_process' +import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' +import { readState } from '@dotcom-tool-kit/state' +import { Task } from '@dotcom-tool-kit/types' +import { CypressSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/cypress' + +export default class CypressCi extends Task { + async run(): Promise { + const reviewState = readState('review') + const cypressEnv: Record = {} + if (reviewState && reviewState.appName) { + cypressEnv.CYPRESS_BASE_URL = `https://${reviewState.appName}.herokuapp.com` + cypressEnv.CYPRESS_REVIEW_APP = 'true' + } else { + cypressEnv.CYPRESS_BASE_URL = `https://${process.env.CY_CUSTOM_DOMAIN_STAGING}` + } + + this.logger.info(`running cypress against ${cypressEnv.CYPRESS_BASEURL}`) + const testProcess = spawn('cypress', ['run'], { env: { ...process.env, ...cypressEnv } }) + hookFork(this.logger, 'cypress', testProcess) + return waitOnExit('cypress', testProcess) + } +} diff --git a/plugins/cypress/src/tasks/cypress.ts b/plugins/cypress/src/tasks/local.ts similarity index 54% rename from plugins/cypress/src/tasks/cypress.ts rename to plugins/cypress/src/tasks/local.ts index 2c2040ed9..799a28a4d 100644 --- a/plugins/cypress/src/tasks/cypress.ts +++ b/plugins/cypress/src/tasks/local.ts @@ -5,7 +5,7 @@ import { readState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/types' import { CypressSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/cypress' -export class CypressLocal extends Task { +export default class CypressLocal extends Task { async run(): Promise { const cypressEnv: Record = {} if (this.options.localUrl) { @@ -22,21 +22,3 @@ export class CypressLocal extends Task { return waitOnExit('cypress', testProcess) } } - -export class CypressCi extends Task { - async run(): Promise { - const reviewState = readState('review') - const cypressEnv: Record = {} - if (reviewState && reviewState.appName) { - cypressEnv.CYPRESS_BASE_URL = `https://${reviewState.appName}.herokuapp.com` - cypressEnv.CYPRESS_REVIEW_APP = 'true' - } else { - cypressEnv.CYPRESS_BASE_URL = `https://${process.env.CY_CUSTOM_DOMAIN_STAGING}` - } - - this.logger.info(`running cypress against ${cypressEnv.CYPRESS_BASE_URL}`) - const testProcess = spawn('cypress', ['run'], { env: { ...process.env, ...cypressEnv } }) - hookFork(this.logger, 'cypress', testProcess) - return waitOnExit('cypress', testProcess) - } -} diff --git a/plugins/eslint/.toolkitrc.yml b/plugins/eslint/.toolkitrc.yml index 4c78bd98c..e74177acc 100644 --- a/plugins/eslint/.toolkitrc.yml +++ b/plugins/eslint/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - - Eslint + Eslint: './lib/tasks/eslint' commands: 'test:local': Eslint diff --git a/plugins/eslint/src/index.ts b/plugins/eslint/src/index.ts deleted file mode 100644 index 062f70512..000000000 --- a/plugins/eslint/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Eslint from './tasks/eslint' - -export const tasks = { Eslint } diff --git a/plugins/heroku/.toolkitrc.yml b/plugins/heroku/.toolkitrc.yml index 0e5cb4a2f..bd7a8023f 100644 --- a/plugins/heroku/.toolkitrc.yml +++ b/plugins/heroku/.toolkitrc.yml @@ -3,10 +3,10 @@ plugins: - '@dotcom-tool-kit/doppler' # required so the create script knows we need its options tasks: - - HerokuProduction - - HerokuStaging - - HerokuReview - - HerokuTeardown + HerokuProduction: './lib/tasks/production' + HerokuStaging: './lib/tasks/staging' + HerokuReview: './lib/tasks/review' + HerokuTeardown: './lib/tasks/teardown' commands: 'cleanup:remote': NpmPrune diff --git a/plugins/heroku/src/index.ts b/plugins/heroku/src/index.ts deleted file mode 100644 index 8caaef3d4..000000000 --- a/plugins/heroku/src/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import HerokuProduction from './tasks/production' -import HerokuStaging from './tasks/staging' -import HerokuReview from './tasks/review' -import HerokuTeardown from './tasks/teardown' - -export const tasks = { HerokuProduction, HerokuStaging, HerokuReview, HerokuTeardown } diff --git a/plugins/jest/.toolkitrc.yml b/plugins/jest/.toolkitrc.yml index c27583b36..279f39daf 100644 --- a/plugins/jest/.toolkitrc.yml +++ b/plugins/jest/.toolkitrc.yml @@ -1,6 +1,6 @@ tasks: - - JestLocal - - JestCI + JestLocal: './lib/tasks/local' + JestCI: './lib/tasks/ci' commands: 'test:local': JestLocal diff --git a/plugins/jest/src/index.ts b/plugins/jest/src/index.ts deleted file mode 100644 index 844b10624..000000000 --- a/plugins/jest/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import JestCI from './tasks/ci' -import JestLocal from './tasks/local' - -export const tasks = { - JestCI, - JestLocal -} diff --git a/plugins/lint-staged/.toolkitrc.yml b/plugins/lint-staged/.toolkitrc.yml index 0809c4906..ba50cab20 100644 --- a/plugins/lint-staged/.toolkitrc.yml +++ b/plugins/lint-staged/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - - LintStaged + LintStaged: './lib/tasks/lint-staged' commands: 'git:precommit': LintStaged diff --git a/plugins/lint-staged/src/hook.ts b/plugins/lint-staged/src/hook.ts deleted file mode 100644 index ccb70d9c5..000000000 --- a/plugins/lint-staged/src/hook.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PackageJsonHelper } from '@dotcom-tool-kit/package-json-hook' - -export abstract class LintStagedHook extends PackageJsonHelper { - field = 'lint-staged' - trailingString = '--' -} diff --git a/plugins/lint-staged/src/index.ts b/plugins/lint-staged/src/index.ts deleted file mode 100644 index 68f006aed..000000000 --- a/plugins/lint-staged/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import LintStaged from './tasks/lint-staged' - -export const tasks = { LintStaged } -export { LintStagedHook } from './hook' diff --git a/plugins/mocha/.toolkitrc.yml b/plugins/mocha/.toolkitrc.yml index d08af250b..678446b2d 100644 --- a/plugins/mocha/.toolkitrc.yml +++ b/plugins/mocha/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - - Mocha + Mocha: './lib/tasks/mocha' commands: 'test:local': Mocha diff --git a/plugins/mocha/src/index.ts b/plugins/mocha/src/index.ts deleted file mode 100644 index 4a82c28bd..000000000 --- a/plugins/mocha/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Mocha from './tasks/mocha' - -export const tasks = { Mocha } diff --git a/plugins/n-test/.toolkitrc.yml b/plugins/n-test/.toolkitrc.yml index 62c144f9b..450a496d0 100644 --- a/plugins/n-test/.toolkitrc.yml +++ b/plugins/n-test/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - - NTest + NTest: './lib/tasks/n-test' commands: 'test:review': NTest diff --git a/plugins/n-test/src/index.ts b/plugins/n-test/src/index.ts deleted file mode 100644 index faefa7cf7..000000000 --- a/plugins/n-test/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import NTest from './tasks/n-test' - -export const tasks = { NTest } diff --git a/plugins/next-router/.toolkitrc.yml b/plugins/next-router/.toolkitrc.yml index 417fca097..137fc6d9f 100644 --- a/plugins/next-router/.toolkitrc.yml +++ b/plugins/next-router/.toolkitrc.yml @@ -2,7 +2,7 @@ plugins: - '@dotcom-tool-kit/doppler' tasks: - - NextRouter + NextRouter: './lib/tasks/next-router' commands: run:local: diff --git a/plugins/next-router/src/index.ts b/plugins/next-router/src/index.ts deleted file mode 100644 index 2c56dc58f..000000000 --- a/plugins/next-router/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import NextRouter from './tasks/next-router' - -export const tasks = { NextRouter } diff --git a/plugins/node/.toolkitrc.yml b/plugins/node/.toolkitrc.yml index 32b662bd2..32968f1d0 100644 --- a/plugins/node/.toolkitrc.yml +++ b/plugins/node/.toolkitrc.yml @@ -2,7 +2,7 @@ plugins: - '@dotcom-tool-kit/doppler' tasks: - - Node + Node: './lib/tasks/node' commands: 'run:local': Node diff --git a/plugins/node/src/index.ts b/plugins/node/src/index.ts deleted file mode 100644 index 9cbead2f9..000000000 --- a/plugins/node/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Node from './tasks/node' - -export const tasks = { Node } diff --git a/plugins/nodemon/.toolkitrc.yml b/plugins/nodemon/.toolkitrc.yml index ba8ac1459..9eb48e671 100644 --- a/plugins/nodemon/.toolkitrc.yml +++ b/plugins/nodemon/.toolkitrc.yml @@ -2,7 +2,7 @@ plugins: - '@dotcom-tool-kit/doppler' tasks: - - Nodemon + Nodemon: './lib/tasks/nodemon' commands: 'run:local': Nodemon diff --git a/plugins/nodemon/src/index.ts b/plugins/nodemon/src/index.ts deleted file mode 100644 index 91125b1f2..000000000 --- a/plugins/nodemon/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Nodemon from './tasks/nodemon' - -export const tasks = { Nodemon } diff --git a/plugins/npm/.toolkitrc.yml b/plugins/npm/.toolkitrc.yml index 2277d7455..84bb831cb 100644 --- a/plugins/npm/.toolkitrc.yml +++ b/plugins/npm/.toolkitrc.yml @@ -1,3 +1,3 @@ tasks: - - NpmPrune - - NpmPublish + NpmPrune: './lib/tasks/prune' + NpmPublish: './lib/tasks/publish' diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts index 8e432f321..36d2bc833 100644 --- a/plugins/npm/src/index.ts +++ b/plugins/npm/src/index.ts @@ -1,10 +1 @@ -import { PackageJsonScriptHook } from '@dotcom-tool-kit/package-json-hook' -import NpmPrune from './tasks/npm-prune' -import NpmPublish from './tasks/npm-publish' - -export { PackageJsonScriptHook as PackageJsonScriptHook } - -export const tasks = { - NpmPrune, - NpmPublish -} +export { PackageJsonScriptHook } from '@dotcom-tool-kit/package-json-hook' diff --git a/plugins/npm/src/tasks/npm-prune.ts b/plugins/npm/src/tasks/prune.ts similarity index 100% rename from plugins/npm/src/tasks/npm-prune.ts rename to plugins/npm/src/tasks/prune.ts diff --git a/plugins/npm/src/tasks/npm-publish.ts b/plugins/npm/src/tasks/publish.ts similarity index 100% rename from plugins/npm/src/tasks/npm-publish.ts rename to plugins/npm/src/tasks/publish.ts diff --git a/plugins/pa11y/.toolkitrc.yml b/plugins/pa11y/.toolkitrc.yml index 807c09ef3..5b2d35376 100644 --- a/plugins/pa11y/.toolkitrc.yml +++ b/plugins/pa11y/.toolkitrc.yml @@ -2,7 +2,7 @@ plugins: - '@dotcom-tool-kit/doppler' tasks: - - Pa11y + Pa11y: './lib/tasks/pa11y' commands: 'test:local': Pa11y diff --git a/plugins/pa11y/src/index.ts b/plugins/pa11y/src/index.ts deleted file mode 100644 index 381ca3f19..000000000 --- a/plugins/pa11y/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Pa11y from './tasks/pa11y' - -export const tasks = { Pa11y } diff --git a/plugins/prettier/.toolkitrc.yml b/plugins/prettier/.toolkitrc.yml index 7434c75c5..7d31a908c 100644 --- a/plugins/prettier/.toolkitrc.yml +++ b/plugins/prettier/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - - Prettier + Prettier: './lib/tasks/prettier' commands: 'format:local': Prettier diff --git a/plugins/prettier/src/index.ts b/plugins/prettier/src/index.ts deleted file mode 100644 index 165bad0c8..000000000 --- a/plugins/prettier/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import Prettier from './tasks/prettier' - -export const tasks = { Prettier } diff --git a/plugins/serverless/.toolkitrc.yml b/plugins/serverless/.toolkitrc.yml index bd06dec03..9549aa534 100644 --- a/plugins/serverless/.toolkitrc.yml +++ b/plugins/serverless/.toolkitrc.yml @@ -1,4 +1,4 @@ tasks: - - ServerlessRun - - ServerlessDeploy - - ServerlessProvision + ServerlessRun: './lib/tasks/run' + ServerlessDeploy: './lib/tasks/deploy' + ServerlessProvision: './lib/tasks/provision' diff --git a/plugins/serverless/src/index.ts b/plugins/serverless/src/index.ts deleted file mode 100644 index 687fade58..000000000 --- a/plugins/serverless/src/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import ServerlessDeploy from './tasks/deploy' -import ServerlessProvision from './tasks/provision' -import ServerlessRun from './tasks/run' -import ServerlessTeardown from './tasks/teardown' - -export const tasks = { ServerlessRun, ServerlessDeploy, ServerlessProvision, ServerlessTeardown } diff --git a/plugins/typescript/.toolkitrc.yml b/plugins/typescript/.toolkitrc.yml index c824863f3..f7b191149 100644 --- a/plugins/typescript/.toolkitrc.yml +++ b/plugins/typescript/.toolkitrc.yml @@ -1,7 +1,7 @@ tasks: - - TypeScriptBuild - - TypeScriptWatch - - TypeScriptTest + TypeScriptBuild: './lib/tasks/build' + TypeScriptWatch: './lib/tasks/watch' + TypeScriptTest: './lib/tasks/test' commands: 'build:local': TypeScriptBuild diff --git a/plugins/typescript/src/index.ts b/plugins/typescript/src/index.ts deleted file mode 100644 index d5928b163..000000000 --- a/plugins/typescript/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { TypeScriptBuild, TypeScriptWatch, TypeScriptTest } from './tasks/typescript' - -export const tasks = { TypeScriptBuild, TypeScriptWatch, TypeScriptTest } diff --git a/plugins/typescript/src/tasks/build.ts b/plugins/typescript/src/tasks/build.ts new file mode 100644 index 000000000..ce9610b25 --- /dev/null +++ b/plugins/typescript/src/tasks/build.ts @@ -0,0 +1,7 @@ +import TypeScriptTask from './typescript' + +export default class TypeScriptBuild extends TypeScriptTask { + static description = 'compile TypeScript to JavaScript' + + taskArgs = [] +} diff --git a/plugins/typescript/src/tasks/test.ts b/plugins/typescript/src/tasks/test.ts new file mode 100644 index 000000000..f333c6ae6 --- /dev/null +++ b/plugins/typescript/src/tasks/test.ts @@ -0,0 +1,7 @@ +import TypeScriptTask from './typescript' + +export default class TypeScriptTest extends TypeScriptTask { + static description = 'type check TypeScript code' + + taskArgs = ['--noEmit'] +} diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index 510313ce0..e4c4b032d 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -5,7 +5,7 @@ import { fork } from 'child_process' const tscPath = require.resolve('typescript/bin/tsc') -abstract class TypeScriptTask extends Task { +export default abstract class TypeScriptTask extends Task { abstract taskArgs: string[] async run(): Promise { @@ -30,21 +30,3 @@ abstract class TypeScriptTask extends Task { this.logger.info('code compiled successfully') } } - -export class TypeScriptBuild extends TypeScriptTask { - static description = 'compile TypeScript to JavaScript' - - taskArgs = [] -} - -export class TypeScriptWatch extends TypeScriptTask { - static description = 'rebuild TypeScript project every file change' - - taskArgs = ['--watch'] -} - -export class TypeScriptTest extends TypeScriptTask { - static description = 'type check TypeScript code' - - taskArgs = ['--noEmit'] -} diff --git a/plugins/typescript/src/tasks/watch.ts b/plugins/typescript/src/tasks/watch.ts new file mode 100644 index 000000000..43e79161b --- /dev/null +++ b/plugins/typescript/src/tasks/watch.ts @@ -0,0 +1,7 @@ +import TypeScriptTask from './typescript' + +export default class TypeScriptWatch extends TypeScriptTask { + static description = 'rebuild TypeScript project every file change' + + taskArgs = ['--watch'] +} diff --git a/plugins/upload-assets-to-s3/.toolkitrc.yml b/plugins/upload-assets-to-s3/.toolkitrc.yml index 36ad7483a..1388260a4 100644 --- a/plugins/upload-assets-to-s3/.toolkitrc.yml +++ b/plugins/upload-assets-to-s3/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - - UploadAssetsToS3 + UploadAssetsToS3: './lib/tasks/upload-assets-to-s3' commands: 'release:remote': UploadAssetsToS3 diff --git a/plugins/upload-assets-to-s3/src/index.ts b/plugins/upload-assets-to-s3/src/index.ts deleted file mode 100644 index dc8838fa5..000000000 --- a/plugins/upload-assets-to-s3/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import UploadAssetsToS3 from './tasks/upload-assets-to-s3' - -export const tasks = { UploadAssetsToS3 } diff --git a/plugins/webpack/.toolkitrc.yml b/plugins/webpack/.toolkitrc.yml index 4333f40bd..2840e88d6 100644 --- a/plugins/webpack/.toolkitrc.yml +++ b/plugins/webpack/.toolkitrc.yml @@ -1,7 +1,7 @@ tasks: - - WebpackDevelopment - - WebpackProduction - - WebpackWatch + WebpackDevelopment: './lib/tasks/development' + WebpackProduction: './lib/tasks/production' + WebpackWatch: './lib/tasks/watch' commands: 'build:local': WebpackDevelopment diff --git a/plugins/webpack/src/index.ts b/plugins/webpack/src/index.ts deleted file mode 100644 index 6d60e8fca..000000000 --- a/plugins/webpack/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import WebpackDevelopment from './tasks/development' -import WebpackProduction from './tasks/production' -import WebpackWatch from './tasks/watch' - -export const tasks = { WebpackDevelopment, WebpackProduction, WebpackWatch } From 970de5d2af24590154f79bd2ba19a8e112d38bab Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 16:09:28 +0000 Subject: [PATCH 032/321] refactor: use resolve-pkg instead of resolve-from now that most plugins don't have entry points --- core/cli/package.json | 2 +- core/cli/src/plugin.ts | 15 ++++++--------- package-lock.json | 13 ++++++++++++- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/core/cli/package.json b/core/cli/package.json index 27e29b919..d9a91f7e2 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -48,7 +48,7 @@ "cosmiconfig": "^7.0.0", "lodash": "^4.17.21", "minimist": "^1.2.5", - "resolve-from": "^5.0.0", + "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", "yaml": "^1.10.2", "zod-validation-error": "^0.3.0" diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index f3c4bf3b9..451a55da2 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -7,7 +7,7 @@ import { Valid, Validated } from '@dotcom-tool-kit/types' -import resolveFrom from 'resolve-from' +import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' import { EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' import { Conflict, isConflict } from './conflict' @@ -34,10 +34,9 @@ export async function importEntryPoint> { - let resolvedPath: string - try { - resolvedPath = resolveFrom(entryPoint.plugin.root, entryPoint.modulePath) - } catch (e) { + const resolvedPath = resolvePkg(entryPoint.modulePath, { cwd: entryPoint.plugin.root }) + + if (!resolvedPath) { return { valid: false, reasons: [ @@ -104,10 +103,8 @@ export async function loadPlugin( // load plugin relative to the parent plugin const root = parent ? parent.root : process.cwd() - let pluginRoot: string - try { - pluginRoot = isAppRoot ? root : resolveFrom(root, id) - } catch (e) { + const pluginRoot = isAppRoot ? root : resolvePkg(id, { cwd: root }) + if (!pluginRoot) { return { valid: false, reasons: [`could not find path for name ${s.filepath(id)}`] } } diff --git a/package-lock.json b/package-lock.json index 1dd4ac94c..393a21054 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,7 +58,7 @@ "cosmiconfig": "^7.0.0", "lodash": "^4.17.21", "minimist": "^1.2.5", - "resolve-from": "^5.0.0", + "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", "yaml": "^1.10.2", "zod-validation-error": "^0.3.0" @@ -23838,6 +23838,17 @@ "node": ">=8" } }, + "node_modules/resolve-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz", + "integrity": "sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-url": { "version": "0.2.1", "license": "MIT" From 3816e69c3e7bbcd2de246786fdad6c6e3c934f17 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 16:11:23 +0000 Subject: [PATCH 033/321] feat: add command for printing the full config, useful for debugging --- core/cli/bin/run | 3 +++ core/cli/src/index.ts | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/core/cli/bin/run b/core/cli/bin/run index aeec5d51e..6ace64050 100755 --- a/core/cli/bin/run +++ b/core/cli/bin/run @@ -15,6 +15,9 @@ async function main() { } else if (argv.listPlugins) { const { listPlugins } = require('../lib') await listPlugins(rootLogger) + } else if (argv.printConfig) { + const { printConfig } = require('../lib') + await printConfig(rootLogger) } else if (argv.help || argv._.length === 0) { const showHelp = require('../lib/help').default await showHelp(rootLogger, argv._) diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 10dacdbcd..2156a9497 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -3,6 +3,7 @@ import { ValidConfig, checkInstall, loadConfig } from './config' import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' +import util from 'util' import { formatPluginTree } from './messages' import { Task, @@ -147,3 +148,9 @@ export async function listPlugins(logger: Logger): Promise { logger.info(formatPluginTree(rootPlugin.value).join('\n')) } } + +export async function printConfig(logger: Logger): Promise { + const config = await loadConfig(logger, { validate: false }) + + logger.info(util.inspect(config, { depth: null, colors: true })) +} From aebaec9b267737c918e0fe382ab920d2841706bf Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 16:18:21 +0000 Subject: [PATCH 034/321] test: fix import for npm publish test --- plugins/npm/test/npm-publish.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/npm/test/npm-publish.test.ts b/plugins/npm/test/npm-publish.test.ts index bb33fe557..4747cb9f1 100644 --- a/plugins/npm/test/npm-publish.test.ts +++ b/plugins/npm/test/npm-publish.test.ts @@ -1,5 +1,5 @@ import { semVerRegex } from '@dotcom-tool-kit/types/lib/npm' -import NpmPublish from '../src/tasks/npm-publish' +import NpmPublish from '../src/tasks/publish' import winston, { Logger } from 'winston' import { ToolKitError } from '../../../lib/error/lib' import * as state from '@dotcom-tool-kit/state' From 81281d3c3f5e7de4e990bc5998eb33df6a26aeb2 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 16:22:28 +0000 Subject: [PATCH 035/321] test: delete the plugin validity integration test it was originally added to verify that every plugin entrypoint exported the correct structure. now plugins declare their task and hook entry points in the toolkitrc.yml there's less chance of an entrypoint not exporting things correctly. --- core/cli/test/plugin.test.ts | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 core/cli/test/plugin.test.ts diff --git a/core/cli/test/plugin.test.ts b/core/cli/test/plugin.test.ts deleted file mode 100644 index f9ac9a22b..000000000 --- a/core/cli/test/plugin.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { describe, it } from '@jest/globals' -import fs from 'fs' -import path from 'path' -import { RawPluginModule, importPlugin, validatePluginHooks, validatePluginTasks } from '../src/plugin' -import { unwrapValidated } from '@dotcom-tool-kit/types' - -const pluginDir = path.join(__dirname, '../../../plugins') - -function getPlugins() { - const pluginDirContents = fs.readdirSync(pluginDir, { withFileTypes: true }) - return pluginDirContents.filter((plugin) => plugin.isDirectory()).map((plugin) => plugin.name) -} - -describe.each(getPlugins())('%s integration test', (pluginName) => { - const packagePath = path.join(pluginDir, pluginName) - let plugin: RawPluginModule - - beforeAll(async () => { - plugin = unwrapValidated(await importPlugin(packagePath)) as RawPluginModule - }) - - it('should have valid tasks', () => { - const tasks = validatePluginTasks(plugin) - expect(tasks).not.toHaveProperty('reasons') - }) - - it('should have valid hooks', () => { - const hooks = validatePluginHooks(plugin) - expect(hooks).not.toHaveProperty('reasons') - }) -}) From 290cb406d56989167bd210aa101a3ada3ca95a56 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 16:38:39 +0000 Subject: [PATCH 036/321] test: don't consider files just called `test.ts` tests --- jest.config.base.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.base.js b/jest.config.base.js index 14634afd8..7813c156a 100644 --- a/jest.config.base.js +++ b/jest.config.base.js @@ -1,6 +1,7 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', + testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/*.+(spec|test).[jt]s?(x)'], testPathIgnorePatterns: ['/node_modules/', '/.+/lib/', '/test/files'], clearMocks: true, globals: { From 85ca289c4ffb85f5c8dda77ef0c18bcaf7201daf Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 17 Nov 2023 17:07:12 +0000 Subject: [PATCH 037/321] test: fix typescript test imports --- plugins/typescript/test/tasks/typescript.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/typescript/test/tasks/typescript.test.ts b/plugins/typescript/test/tasks/typescript.test.ts index a733c7a2e..dd1050db4 100644 --- a/plugins/typescript/test/tasks/typescript.test.ts +++ b/plugins/typescript/test/tasks/typescript.test.ts @@ -1,5 +1,7 @@ import { describe, jest, it, expect } from '@jest/globals' -import { TypeScriptBuild, TypeScriptWatch, TypeScriptTest } from '../../src/tasks/typescript' +import TypeScriptBuild from '../../src/tasks/build' +import TypeScriptWatch from '../../src/tasks/watch' +import TypeScriptTest from '../../src/tasks/test' import { fork } from 'child_process' import EventEmitter from 'events' import winston, { Logger } from 'winston' From d2c290ba08cfba334f5eacec489127144f24e79f Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 21 Nov 2023 13:57:14 +0000 Subject: [PATCH 038/321] test: skip the conflicting test because it can't pass until command assignments can conflict again --- core/cli/test/index.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index 42f98fe2b..97ab6b9b0 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -12,7 +12,9 @@ const logger = (winston as unknown) as Logger jest.setTimeout(20000) describe('cli', () => { - it('should indicate when there are conflicts', async () => { + // TODO:KB:202301121 we only return conflicts for hooks that are defined. + // currently there are no hooks lol + it.skip('should indicate when there are conflicts', async () => { const config = createConfig() const plugin = await loadPlugin('app root', config, logger, { From 2e7c423e560752cd578d901fabbbea155c64be39 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Wed, 22 Nov 2023 14:24:00 +0000 Subject: [PATCH 039/321] chore(circleci)!: bump default CircleCI node image used to Node 18 Don't love that this is a breaking change for the types package rather than for circleci but types is going to be getting a major version bump from other changes in the next branch anyway. --- lib/types/src/schema/plugins/circleci.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/src/schema/plugins/circleci.ts b/lib/types/src/schema/plugins/circleci.ts index 55fc414d5..a655d13cc 100644 --- a/lib/types/src/schema/plugins/circleci.ts +++ b/lib/types/src/schema/plugins/circleci.ts @@ -1,7 +1,7 @@ import { z } from 'zod' export const CircleCISchema = z.object({ - nodeVersion: z.string().or(z.string().array()).default('16.14-browsers'), + nodeVersion: z.string().or(z.string().array()).default('18.18-browsers'), cypressImage: z.string().optional() }) export type CircleCIOptions = z.infer From 78d331d4a8ddfdaf22ef6b8a81cdf28c210461a5 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 19 Oct 2023 13:41:12 +0100 Subject: [PATCH 040/321] refactor: move conflict types and handlers to types package --- core/cli/src/config.ts | 8 +++++++- core/cli/src/messages.ts | 2 +- core/cli/src/plugin.ts | 2 +- {core/cli => lib/types}/src/conflict.ts | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) rename {core/cli => lib/types}/src/conflict.ts (94%) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index db3058cbe..71323b464 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -6,7 +6,13 @@ import type { Logger } from 'winston' import type { CommandTask } from './command' import { importEntryPoint, loadPlugin, resolvePlugin } from './plugin' -import { Conflict, findConflicts, withoutConflicts, isConflict, findConflictingEntries } from './conflict' +import { + Conflict, + findConflicts, + withoutConflicts, + isConflict, + findConflictingEntries +} from '@dotcom-tool-kit/types/lib/conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' import { diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 25f89905d..7bb7aec07 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -3,7 +3,7 @@ import type { Hook, Plugin } from '@dotcom-tool-kit/types' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' import type { EntryPoint, PluginOptions } from './config' -import type { Conflict } from './conflict' +import type { Conflict } from '@dotcom-tool-kit/types/lib/conflict' import type { CommandTask } from './command' const formatTaskConflict = ([key, conflict]: [string, Conflict]): string => diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 451a55da2..cd906d885 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -10,7 +10,7 @@ import { import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' import { EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' -import { Conflict, isConflict } from './conflict' +import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' import { isPlainObject } from 'lodash' diff --git a/core/cli/src/conflict.ts b/lib/types/src/conflict.ts similarity index 94% rename from core/cli/src/conflict.ts rename to lib/types/src/conflict.ts index 9fee842de..ed5cf90bb 100644 --- a/core/cli/src/conflict.ts +++ b/lib/types/src/conflict.ts @@ -1,4 +1,4 @@ -import type { Plugin } from '@dotcom-tool-kit/types' +import type { Plugin } from './' export interface Conflict { plugin: Plugin From a4d6af0a81deb65afde3c021f5aac8d2534a88e4 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 23 Nov 2023 12:38:52 +0000 Subject: [PATCH 041/321] style: include index in import path Co-authored-by: Ivo Murrell --- lib/types/src/conflict.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/src/conflict.ts b/lib/types/src/conflict.ts index ed5cf90bb..dba0be814 100644 --- a/lib/types/src/conflict.ts +++ b/lib/types/src/conflict.ts @@ -1,4 +1,4 @@ -import type { Plugin } from './' +import type { Plugin } from './index' export interface Conflict { plugin: Plugin From 38dd5391fa5f706926387479faca7ba2b9bbefdc Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 23 Nov 2023 16:53:00 +0000 Subject: [PATCH 042/321] chore!: delete the husky hook --- plugins/husky-npm/src/husky-hook.ts | 5 ----- plugins/husky-npm/src/index.ts | 1 - 2 files changed, 6 deletions(-) delete mode 100644 plugins/husky-npm/src/husky-hook.ts diff --git a/plugins/husky-npm/src/husky-hook.ts b/plugins/husky-npm/src/husky-hook.ts deleted file mode 100644 index 50adcfc15..000000000 --- a/plugins/husky-npm/src/husky-hook.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { PackageJsonHelper } from '@dotcom-tool-kit/package-json-hook' - -export abstract class HuskyHook extends PackageJsonHelper { - field = ['husky', 'hooks'] -} diff --git a/plugins/husky-npm/src/index.ts b/plugins/husky-npm/src/index.ts index 43ef84c5e..e69de29bb 100644 --- a/plugins/husky-npm/src/index.ts +++ b/plugins/husky-npm/src/index.ts @@ -1 +0,0 @@ -export { HuskyHook } from './husky-hook' From 9bda25d45875bfd951f674f1895c133d237e2999 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 27 Nov 2023 12:27:05 +0000 Subject: [PATCH 043/321] chore: update the types for libnpmpublish and tar --- package-lock.json | 61 +++++++++++++++++--------------- plugins/npm/package.json | 5 +-- plugins/npm/src/tasks/publish.ts | 9 +++-- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/package-lock.json b/package-lock.json index 393a21054..6b68ec505 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9478,15 +9478,6 @@ "@types/node": "*" } }, - "node_modules/@types/libnpmpublish": { - "version": "4.0.1", - "dev": true, - "dependencies": { - "@npm/types": "*", - "@types/node-fetch": "*", - "@types/npm-registry-fetch": "*" - } - }, "node_modules/@types/lodash": { "version": "4.14.189", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.189.tgz", @@ -9674,23 +9665,6 @@ "@types/node": "*" } }, - "node_modules/@types/tar": { - "version": "6.1.1", - "dev": true, - "dependencies": { - "@types/node": "*", - "minipass": "^4.0.0" - } - }, - "node_modules/@types/tar/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@types/tough-cookie": { "version": "4.0.2", "license": "MIT" @@ -29926,9 +29900,10 @@ "tslib": "^2.3.1" }, "devDependencies": { - "@types/libnpmpublish": "^4.0.1", + "@npm/types": "^1.0.2", + "@types/libnpmpublish": "^4.0.6", "@types/pacote": "^11.1.3", - "@types/tar": "^6.1.1", + "@types/tar": "^6.1.10", "winston": "^3.5.1" }, "engines": { @@ -29954,6 +29929,36 @@ "which": "^2.0.2" } }, + "plugins/npm/node_modules/@types/libnpmpublish": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/libnpmpublish/-/libnpmpublish-4.0.6.tgz", + "integrity": "sha512-xI99EEgpr1R0hpLAKb52QbBYv8ZZa9FDiZS7LEVE6RevjkQHF3BflPR7Mo2F8yxMnqP6eoPkWE0bnWvDC/sA9A==", + "dev": true, + "dependencies": { + "@npm/types": "*", + "@types/node-fetch": "*", + "@types/npm-registry-fetch": "*" + } + }, + "plugins/npm/node_modules/@types/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-ThA1WD8aDdVU4VLuyq5NEqriwXErF5gEIJeyT6gHBWU7JtSmW2a5qjNv3/vR82O20mW+1vhmeZJfBQPT3HCugg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "minipass": "^4.0.0" + } + }, + "plugins/npm/node_modules/@types/tar/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "plugins/npm/node_modules/ignore-walk": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", diff --git a/plugins/npm/package.json b/plugins/npm/package.json index e087b4741..54124b43f 100644 --- a/plugins/npm/package.json +++ b/plugins/npm/package.json @@ -29,9 +29,10 @@ "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/npm", "devDependencies": { - "@types/libnpmpublish": "^4.0.1", + "@npm/types": "^1.0.2", + "@types/libnpmpublish": "^4.0.6", "@types/pacote": "^11.1.3", - "@types/tar": "^6.1.1", + "@types/tar": "^6.1.10", "winston": "^3.5.1" }, "files": [ diff --git a/plugins/npm/src/tasks/publish.ts b/plugins/npm/src/tasks/publish.ts index 9796bf8ea..acd2bcdc8 100644 --- a/plugins/npm/src/tasks/publish.ts +++ b/plugins/npm/src/tasks/publish.ts @@ -9,6 +9,7 @@ import { publish } from 'libnpmpublish' import { styles } from '@dotcom-tool-kit/logger' import tar from 'tar' import { PassThrough as PassThroughStream } from 'stream' +import type { PackageJson } from '@npm/types' type TagType = 'prerelease' | 'latest' @@ -37,7 +38,7 @@ export default class NpmPublish extends Task { new PassThroughStream() .end(tarball) - .pipe(tar.t({ onentry: (entry) => this.logger.info(`- ${styles.filepath(entry.header.path)}`) })) + .pipe(tar.t({ onentry: (entry) => this.logger.info(`- ${styles.filepath(entry.path)}`) })) } async run(): Promise { @@ -73,7 +74,11 @@ export default class NpmPublish extends Task { await this.listPackedFiles(tarball) - await publish(manifest, tarball, { + // HACK:KB:20231127 cast the manifest to a PackageJson. libnpmpublish expects a + // PackageJson, but pacote.ManifestResult isn't assignable to that, because the + // definition of PackageJson in @npm/types is incorrect lol + // https://github.com/npm/types/pull/18 + await publish(manifest as PackageJson, tarball, { access: 'public', defaultTag: npmTag, forceAuth: { From e36d552f054526e4730781e1cd344d07e090fa6b Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 28 Nov 2023 12:11:52 +0000 Subject: [PATCH 044/321] feat: move package-json-hook to plugins and export PackageJson hook --- .release-please-manifest.json | 2 +- lib/package-json-hook/.toolkitrc.yml | 0 lib/package-json-hook/src/index.ts | 2 -- lib/package-json-hook/src/script-hook.ts | 5 ----- plugins/heroku/tsconfig.json | 2 +- plugins/husky-npm/tsconfig.json | 6 ++---- plugins/lint-staged/tsconfig.json | 2 +- plugins/npm/src/index.ts | 1 - plugins/npm/tsconfig.json | 8 +++----- plugins/package-json-hook/.toolkitrc.yml | 2 ++ {lib => plugins}/package-json-hook/CHANGELOG.md | 0 {lib => plugins}/package-json-hook/jest.config.js | 0 {lib => plugins}/package-json-hook/package.json | 6 +++--- .../package-json-hook/src/package-json-helper.ts | 12 ++++++------ .../test/files/existing-hook/package.json | 0 .../test/files/multiple-hooks/package.json | 0 .../test/files/with-hook/package.json | 0 .../test/files/without-hook/package.json | 0 .../package-json-hook/test/index.test.ts | 2 +- {lib => plugins}/package-json-hook/tsconfig.json | 6 ++---- release-please-config.json | 2 +- tsconfig.json | 2 +- 22 files changed, 24 insertions(+), 36 deletions(-) delete mode 100644 lib/package-json-hook/.toolkitrc.yml delete mode 100644 lib/package-json-hook/src/index.ts delete mode 100644 lib/package-json-hook/src/script-hook.ts delete mode 100644 plugins/npm/src/index.ts create mode 100644 plugins/package-json-hook/.toolkitrc.yml rename {lib => plugins}/package-json-hook/CHANGELOG.md (100%) rename {lib => plugins}/package-json-hook/jest.config.js (100%) rename {lib => plugins}/package-json-hook/package.json (84%) rename {lib => plugins}/package-json-hook/src/package-json-helper.ts (87%) rename {lib => plugins}/package-json-hook/test/files/existing-hook/package.json (100%) rename {lib => plugins}/package-json-hook/test/files/multiple-hooks/package.json (100%) rename {lib => plugins}/package-json-hook/test/files/with-hook/package.json (100%) rename {lib => plugins}/package-json-hook/test/files/without-hook/package.json (100%) rename {lib => plugins}/package-json-hook/test/index.test.ts (98%) rename {lib => plugins}/package-json-hook/tsconfig.json (72%) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e8cdeea2e..9c108564e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -4,7 +4,7 @@ "lib/error": "3.2.0", "lib/logger": "3.4.0", "lib/options": "3.2.0", - "lib/package-json-hook": "4.2.0", + "plugins/package-json-hook": "4.2.0", "lib/state": "3.3.0", "lib/types": "3.6.0", "lib/vault": "3.2.0", diff --git a/lib/package-json-hook/.toolkitrc.yml b/lib/package-json-hook/.toolkitrc.yml deleted file mode 100644 index e69de29bb..000000000 diff --git a/lib/package-json-hook/src/index.ts b/lib/package-json-hook/src/index.ts deleted file mode 100644 index 4e7ade42b..000000000 --- a/lib/package-json-hook/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { PackageJsonScriptHook, PackageJsonScriptHook as PackageJsonHook } from './script-hook' -export { PackageJsonHelper } from './package-json-helper' diff --git a/lib/package-json-hook/src/script-hook.ts b/lib/package-json-hook/src/script-hook.ts deleted file mode 100644 index 54eca66a0..000000000 --- a/lib/package-json-hook/src/script-hook.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { PackageJsonHelper } from './package-json-helper' - -export abstract class PackageJsonScriptHook extends PackageJsonHelper { - field = 'scripts' -} diff --git a/plugins/heroku/tsconfig.json b/plugins/heroku/tsconfig.json index 36c8ad192..39fdb00f7 100644 --- a/plugins/heroku/tsconfig.json +++ b/plugins/heroku/tsconfig.json @@ -14,7 +14,7 @@ "path": "../../lib/doppler" }, { - "path": "../../lib/package-json-hook" + "path": "../../plugins/package-json-hook" }, { "path": "../npm" diff --git a/plugins/husky-npm/tsconfig.json b/plugins/husky-npm/tsconfig.json index 8470223fa..0939ce186 100644 --- a/plugins/husky-npm/tsconfig.json +++ b/plugins/husky-npm/tsconfig.json @@ -6,10 +6,8 @@ }, "references": [ { - "path": "../../lib/package-json-hook" + "path": "../../plugins/package-json-hook" } ], - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/plugins/lint-staged/tsconfig.json b/plugins/lint-staged/tsconfig.json index 04dfa9bd0..4add90e55 100644 --- a/plugins/lint-staged/tsconfig.json +++ b/plugins/lint-staged/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/package-json-hook" + "path": "../../plugins/package-json-hook" }, { "path": "../../lib/logger" diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts deleted file mode 100644 index 36d2bc833..000000000 --- a/plugins/npm/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { PackageJsonScriptHook } from '@dotcom-tool-kit/package-json-hook' diff --git a/plugins/npm/tsconfig.json b/plugins/npm/tsconfig.json index 8a5c37f81..f46d28df8 100644 --- a/plugins/npm/tsconfig.json +++ b/plugins/npm/tsconfig.json @@ -9,16 +9,14 @@ "path": "../../lib/error" }, { - "path": "../../lib/package-json-hook" + "path": "../../plugins/package-json-hook" }, { "path": "../../lib/types" }, { "path": "../../lib/state" - }, + } ], - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/plugins/package-json-hook/.toolkitrc.yml b/plugins/package-json-hook/.toolkitrc.yml new file mode 100644 index 000000000..b1cc61093 --- /dev/null +++ b/plugins/package-json-hook/.toolkitrc.yml @@ -0,0 +1,2 @@ +installs: + PackageJson: './lib/package-json-helper' diff --git a/lib/package-json-hook/CHANGELOG.md b/plugins/package-json-hook/CHANGELOG.md similarity index 100% rename from lib/package-json-hook/CHANGELOG.md rename to plugins/package-json-hook/CHANGELOG.md diff --git a/lib/package-json-hook/jest.config.js b/plugins/package-json-hook/jest.config.js similarity index 100% rename from lib/package-json-hook/jest.config.js rename to plugins/package-json-hook/jest.config.js diff --git a/lib/package-json-hook/package.json b/plugins/package-json-hook/package.json similarity index 84% rename from lib/package-json-hook/package.json rename to plugins/package-json-hook/package.json index df87115c2..37d925016 100644 --- a/lib/package-json-hook/package.json +++ b/plugins/package-json-hook/package.json @@ -4,7 +4,7 @@ "description": "", "main": "lib", "scripts": { - "test": "cd ../../ ; npx jest --silent --projects lib/package-json-hook" + "test": "cd ../../ ; npx jest --silent --projects plugins/package-json-hook" }, "keywords": [], "author": "FT.com Platforms Team ", @@ -17,10 +17,10 @@ "repository": { "type": "git", "url": "https://github.com/financial-times/dotcom-tool-kit.git", - "directory": "lib/package-json-hook" + "directory": "plugins/package-json-hook" }, "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", - "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/lib/package-json-hook", + "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/package-json-hook", "devDependencies": { "@jest/globals": "^27.4.6", "@types/lodash": "^4.14.185", diff --git a/lib/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts similarity index 87% rename from lib/package-json-hook/src/package-json-helper.ts rename to plugins/package-json-hook/src/package-json-helper.ts index cc3eff4c8..03f07d5da 100644 --- a/lib/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -6,8 +6,8 @@ import merge from 'lodash/merge' import update from 'lodash/update' import path from 'path' -interface PackageJson { - [field: string]: PackageJson | string +interface PackageJsonContents { + [field: string]: PackageJsonContents | string } interface PackageJsonStateValue { @@ -19,8 +19,8 @@ interface PackageJsonState { [field: string]: PackageJsonState | PackageJsonStateValue } -export abstract class PackageJsonHelper extends Hook { - private _packageJson?: PackageJson +export default abstract class PackageJson extends Hook { + private _packageJson?: PackageJsonContents abstract field: string | string[] abstract key: string abstract hook: string @@ -33,7 +33,7 @@ export abstract class PackageJsonHelper extends Hook { filepath = path.resolve(process.cwd(), 'package.json') - async getPackageJson(): Promise { + async getPackageJson(): Promise { if (!this._packageJson) { const rawPackageJson = await fs.promises.readFile(this.filepath, 'utf8') const packageJson = JSON.parse(rawPackageJson) @@ -64,7 +64,7 @@ export abstract class PackageJsonHelper extends Hook { } async commitInstall(state: PackageJsonState): Promise { - const reduceHooks = (state: PackageJsonState): PackageJson => + const reduceHooks = (state: PackageJsonState): PackageJsonContents => mapValues(state, (field) => Array.isArray(field?.hooks) ? `dotcom-tool-kit ${field.hooks.join(' ')}${ diff --git a/lib/package-json-hook/test/files/existing-hook/package.json b/plugins/package-json-hook/test/files/existing-hook/package.json similarity index 100% rename from lib/package-json-hook/test/files/existing-hook/package.json rename to plugins/package-json-hook/test/files/existing-hook/package.json diff --git a/lib/package-json-hook/test/files/multiple-hooks/package.json b/plugins/package-json-hook/test/files/multiple-hooks/package.json similarity index 100% rename from lib/package-json-hook/test/files/multiple-hooks/package.json rename to plugins/package-json-hook/test/files/multiple-hooks/package.json diff --git a/lib/package-json-hook/test/files/with-hook/package.json b/plugins/package-json-hook/test/files/with-hook/package.json similarity index 100% rename from lib/package-json-hook/test/files/with-hook/package.json rename to plugins/package-json-hook/test/files/with-hook/package.json diff --git a/lib/package-json-hook/test/files/without-hook/package.json b/plugins/package-json-hook/test/files/without-hook/package.json similarity index 100% rename from lib/package-json-hook/test/files/without-hook/package.json rename to plugins/package-json-hook/test/files/without-hook/package.json diff --git a/lib/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts similarity index 98% rename from lib/package-json-hook/test/index.test.ts rename to plugins/package-json-hook/test/index.test.ts index 9d187c4f7..1c82c4100 100644 --- a/lib/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from '@jest/globals' import * as path from 'path' import { promises as fs } from 'fs' -import { PackageJsonHelper } from '../src' +import PackageJsonHelper from '../src/package-json-helper' import winston, { Logger } from 'winston' const logger = (winston as unknown) as Logger diff --git a/lib/package-json-hook/tsconfig.json b/plugins/package-json-hook/tsconfig.json similarity index 72% rename from lib/package-json-hook/tsconfig.json rename to plugins/package-json-hook/tsconfig.json index 1c87daee0..318abdeb7 100644 --- a/lib/package-json-hook/tsconfig.json +++ b/plugins/package-json-hook/tsconfig.json @@ -6,10 +6,8 @@ }, "references": [ { - "path": "../types" + "path": "../../lib/types" } ], - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/release-please-config.json b/release-please-config.json index aed5a069f..df950488a 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -11,7 +11,7 @@ "lib/error": {}, "lib/logger": {}, "lib/options": {}, - "lib/package-json-hook": {}, + "plugins/package-json-hook": {}, "lib/state": {}, "lib/types": {}, "lib/vault": {}, diff --git a/tsconfig.json b/tsconfig.json index e24cd1f51..156c0ed52 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -44,7 +44,7 @@ "path": "lib/error" }, { - "path": "lib/package-json-hook" + "path": "plugins/package-json-hook" }, { "path": "plugins/circleci" From 293e3e474a4722fe7f290f56890a7ff2d6c3253b Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 10 Oct 2023 16:23:32 +0100 Subject: [PATCH 045/321] feat: load hook options from rc files and put them in config Co-authored-by: Alex Cerda Co-authored-by: Ivo Murrell --- core/cli/src/config.ts | 21 +++++++++++++++++--- core/cli/src/messages.ts | 19 ++++++++++++++++++- core/cli/src/plugin.ts | 41 +++++++++++++++++++++++++++++++++++++++- core/cli/src/rc-file.ts | 5 +++-- lib/types/src/index.ts | 1 + 5 files changed, 80 insertions(+), 7 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 71323b464..4759cb648 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -35,7 +35,8 @@ import { formatOptionConflicts, formatUninstalledHooks, formatMissingTasks, - formatInvalidOptions + formatInvalidOptions, + formatHookOptionConflicts } from './messages' export interface PluginOptions { @@ -44,6 +45,12 @@ export interface PluginOptions { forPlugin: Plugin } +export interface HookOptions { + options: Record + plugin: Plugin + forHook: string +} + export interface EntryPoint { plugin: Plugin modulePath: string @@ -57,6 +64,7 @@ export interface RawConfig { commandTasks: { [id: string]: CommandTask | Conflict } options: { [id: string]: PluginOptions | Conflict | undefined } hooks: { [id: string]: EntryPoint | Conflict } + hookOptions: { [id: string]: HookOptions | Conflict } } export type ValidPluginsConfig = Omit & { @@ -155,7 +163,8 @@ export const createConfig = (): RawConfig => ({ tasks: {}, commandTasks: {}, options: {}, - hooks: {} + hooks: {}, + hookOptions: {} }) async function asyncFilter(items: T[], predicate: (item: T) => Promise): Promise { @@ -171,6 +180,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali const hookConflicts = findConflictingEntries(config.hooks) const taskConflicts = findConflictingEntries(config.tasks) const optionConflicts = findConflicts(Object.values(config.options)) + const hookOptionConflicts = findConflicts(Object.values(config.hookOptions)) const definedCommandTaskConflicts = commandTaskConflicts.filter((conflict) => { return conflict.conflicting[0].id in config.hooks @@ -192,7 +202,8 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali hookConflicts.length > 0 || definedCommandTaskConflicts.length > 0 || taskConflicts.length > 0 || - optionConflicts.length > 0 + optionConflicts.length > 0 || + hookOptionConflicts.length > 0 ) { shouldThrow = true @@ -211,6 +222,10 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali if (optionConflicts.length) { error.details += formatOptionConflicts(optionConflicts) } + + if (hookOptionConflicts.length) { + error.details += formatHookOptionConflicts(hookOptionConflicts) + } } const configuredCommandTasks = withoutConflicts(Object.values(config.commandTasks)) diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 7bb7aec07..32fae8abc 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -2,7 +2,7 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' import type { Hook, Plugin } from '@dotcom-tool-kit/types' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' -import type { EntryPoint, PluginOptions } from './config' +import type { HookOptions, EntryPoint, PluginOptions } from './config' import type { Conflict } from '@dotcom-tool-kit/types/lib/conflict' import type { CommandTask } from './command' @@ -68,6 +68,23 @@ You must resolve this conflict by providing options in your app's Tool Kit confi ` +const formatHookOptionConflict = (conflict: Conflict): string => `${s.plugin( + conflict.conflicting[0].forHook +)}, configured by: +${conflict.conflicting.map((option) => `- ${s.plugin(option.plugin.id)}`)}` + +export const formatHookOptionConflicts = (conflicts: Conflict[]): string => `${s.heading( + 'These plugins have conflicting options for hooks' +)}: + +${conflicts.map(formatHookOptionConflict).join('\n')} + +You must resolve this conflict by providing options in your app's Tool Kit configuration for these hooks, or installing a use-case plugin that provides these options. See ${s.URL( + 'https://github.com/financial-times/dotcom-tool-kit/tree/main/readme.md#hook-options' +)} for more details. + +` + const formatPlugin = (plugin: Plugin): string => plugin.id === 'app root' ? s.app('your app') : `plugin ${s.plugin(plugin.id)}` diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index cd906d885..4c4147d0c 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -9,7 +9,7 @@ import { } from '@dotcom-tool-kit/types' import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' -import { EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' +import { HookOptions, EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' @@ -273,6 +273,45 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger config.options[pluginId] = pluginOptions } } + + // load plugin hook options. do this after loading child plugins, so + // parent options get assigned after child options and can override them + for (const [id, configHookOptions] of Object.entries(plugin.rcFile.hooks)) { + // users can specify root options with the dotcom-tool-kit key to mirror + // the name of the root npm package + const existingOptions = config.hookOptions[id] + + const hookOptions: HookOptions = { + options: configHookOptions, + plugin, + forHook: id + } + + if (existingOptions) { + const existingFromDescendent = isDescendent(plugin, existingOptions.plugin) + + // plugins can only override options from their descendents, otherwise it's a conflict + // return a conflict either listing these options and the sibling's, + // or merging in previously-generated options + if (!existingFromDescendent) { + const conflicting = isConflict(existingOptions) ? existingOptions.conflicting : [existingOptions] + + const conflict: Conflict = { + plugin, + conflicting: conflicting.concat(hookOptions) + } + + config.hookOptions[id] = conflict + } else { + // if we're here, any existing options are from a child plugin, + // so merge in overrides from the parent + config.hookOptions[id] = { ...existingOptions, ...hookOptions } + } + } else { + // this options key might not have been set yet, in which case use the new one + config.hookOptions[id] = hookOptions + } + } } config.resolvedPlugins.add(plugin) diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 037ef20e3..be26f9f70 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -5,7 +5,7 @@ import * as path from 'path' import type { Logger } from 'winston' export const explorer = cosmiconfig('toolkit', { ignoreEmptySearchPlaces: false }) -const emptyConfig = { plugins: [], installs: {}, tasks: {}, commands: {}, options: {} } +const emptyConfig = { plugins: [], installs: {}, tasks: {}, commands: {}, options: {}, hooks: {} } let rootConfig: string | undefined type RawRCFile = { @@ -38,6 +38,7 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo installs: config.installs ?? {}, tasks: config.tasks ?? {}, commands: config.commands ?? {}, - options: config.options ?? {} + options: config.options ?? {}, + hooks: config.hooks ?? {} } } diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 409fa890d..e0689879a 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -9,6 +9,7 @@ export type RCFile = { tasks: { [id: string]: string } commands: { [id: string]: string | string[] } options: { [id: string]: Record } + hooks: { [id: string]: Record } } export interface Plugin { From 2b884bfd607d5df6e3190b40ab9fa3c225d4572c Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 23 Nov 2023 12:32:57 +0000 Subject: [PATCH 046/321] feat: allow hook classes to specify an options schema Co-authored-by: Ivo Murrell Co-authored-by: Alex Cerda Co-authored-by: Joel Carr --- core/cli/src/config.ts | 15 ++++++++++++--- core/cli/src/messages.ts | 2 +- core/create/src/index.ts | 3 ++- lib/types/src/hook.ts | 9 ++++++--- lib/types/src/hooks.ts | 12 ++++++++++++ plugins/circleci/src/circleci-config.ts | 3 ++- .../package-json-hook/src/package-json-helper.ts | 3 ++- 7 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 lib/types/src/hooks.ts diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 4759cb648..a265e7375 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -3,6 +3,7 @@ import { readFile } from 'node:fs/promises' import path from 'path' import type { Logger } from 'winston' +import { z } from 'zod' import type { CommandTask } from './command' import { importEntryPoint, loadPlugin, resolvePlugin } from './plugin' @@ -25,6 +26,7 @@ import { Validated } from '@dotcom-tool-kit/types' import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' +import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' import { InvalidOption, formatTaskConflicts, @@ -88,12 +90,19 @@ export type ValidConfig = Omit[]>> => { +export const loadHooks = async ( + logger: Logger, + config: ValidConfig +): Promise[]>> => { const hookResults = await Promise.all( Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { - const hookResult = await importEntryPoint(Hook, entryPoint) + const hookResult = (await importEntryPoint(Hook, entryPoint)) as Validated - return mapValidated(hookResult, (Hook) => new ((Hook as unknown) as HookConstructor)(logger, hookName)) + return mapValidated(hookResult, (Hook) => { + const schema = HookSchemas[hookName as keyof HookSchemaOptions] + const options = schema ? schema.parse(config.hookOptions[hookName]) : {} + return new Hook(logger, hookName, options) + }) }) ) diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 32fae8abc..0cacbacd8 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -135,7 +135,7 @@ ${ ` export const formatUninstalledHooks = ( - uninstalledHooks: Hook[] + uninstalledHooks: Hook[] ): string => `These hooks aren't installed into your app: ${uninstalledHooks.map((hook) => `- ${s.hook(hook.id || 'unknown event')}`).join('\n')} diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 4dcadbfcd..5209c5956 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -116,7 +116,8 @@ async function main() { installs: {}, tasks: {}, commands: {}, - options: {} + options: {}, + hooks: {} } const originalCircleConfig = await fsp.readFile(circleConfigPath, 'utf8').catch(() => undefined) diff --git a/lib/types/src/hook.ts b/lib/types/src/hook.ts index fe5245755..740680a78 100644 --- a/lib/types/src/hook.ts +++ b/lib/types/src/hook.ts @@ -1,11 +1,13 @@ import type { Logger } from 'winston' import { Base } from './base' import { hookSymbol, typeSymbol } from './symbols' +import { z } from 'zod' -export abstract class Hook extends Base { +export abstract class Hook extends Base { logger: Logger static description?: string id: string + options: z.output // This field is used to collect hooks that share state when running their // install methods. All hooks in the same group will run their install method // one after the other, and then their commitInstall method will be run with @@ -20,11 +22,12 @@ export abstract class Hook extends Base { return hookSymbol } - constructor(logger: Logger, id: string) { + constructor(logger: Logger, id: string, options: z.output) { super() this.id = id this.logger = logger.child({ hook: this.constructor.name }) + this.options = options } abstract check(): Promise @@ -34,6 +37,6 @@ export abstract class Hook extends Base { } } -export type HookConstructor = { new (logger: Logger, id: string): Hook } +export type HookConstructor = { new (logger: Logger, id: string, options: z.output): Hook } export type HookClass = HookConstructor & typeof Hook diff --git a/lib/types/src/hooks.ts b/lib/types/src/hooks.ts new file mode 100644 index 000000000..2c3b0b259 --- /dev/null +++ b/lib/types/src/hooks.ts @@ -0,0 +1,12 @@ +import { z } from 'zod' + +export const HookSchemas = { + 'dummy schema to get types working for now': z.never() +} + +// Gives the TypeScript type represented by each Schema +export type Options = { + [plugin in keyof typeof HookSchemas]: typeof HookSchemas[plugin] extends z.ZodTypeAny + ? z.infer + : never +} diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index f46b6c51d..a8eb3a17c 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -14,6 +14,7 @@ import omit from 'lodash/omit' import path from 'path' import type { PartialDeep } from 'type-fest' import YAML from 'yaml' +import { z } from 'zod' const MAJOR_ORB_VERSION = '5' @@ -241,7 +242,7 @@ const hasJob = (expectedJob: string, jobs: NonNullable): boole (typeof job === 'object' && job.hasOwnProperty(expectedJob)) ) -export default abstract class CircleCiConfigHook extends Hook { +export default abstract class CircleCiConfigHook extends Hook { installGroup = 'circleci' circleConfigPath = path.resolve(process.cwd(), '.circleci/config.yml') diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index 03f07d5da..c0533b060 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -1,3 +1,4 @@ +import { z } from 'zod' import { Hook } from '@dotcom-tool-kit/types' import fs from 'fs' import get from 'lodash/get' @@ -19,7 +20,7 @@ interface PackageJsonState { [field: string]: PackageJsonState | PackageJsonStateValue } -export default abstract class PackageJson extends Hook { +export default abstract class PackageJson extends Hook { private _packageJson?: PackageJsonContents abstract field: string | string[] abstract key: string From 8e763f0463126847ac2cbe17f3ff9c362a3026b5 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 13 Oct 2023 17:17:24 +0100 Subject: [PATCH 047/321] refactor!: instantiate a separate hook instance per hook installation request from configs --- core/cli/src/config.ts | 26 +++++++++-------------- core/cli/src/messages.ts | 19 +---------------- core/cli/src/plugin.ts | 45 ++++++++-------------------------------- core/cli/src/rc-file.ts | 4 ++-- core/create/src/index.ts | 2 +- lib/types/src/index.ts | 2 +- 6 files changed, 24 insertions(+), 74 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index a265e7375..ba6eb1158 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -37,8 +37,7 @@ import { formatOptionConflicts, formatUninstalledHooks, formatMissingTasks, - formatInvalidOptions, - formatHookOptionConflicts + formatInvalidOptions } from './messages' export interface PluginOptions { @@ -47,7 +46,7 @@ export interface PluginOptions { forPlugin: Plugin } -export interface HookOptions { +export interface HookInstallation { options: Record plugin: Plugin forHook: string @@ -66,7 +65,7 @@ export interface RawConfig { commandTasks: { [id: string]: CommandTask | Conflict } options: { [id: string]: PluginOptions | Conflict | undefined } hooks: { [id: string]: EntryPoint | Conflict } - hookOptions: { [id: string]: HookOptions | Conflict } + hookInstallations: HookInstallation[] } export type ValidPluginsConfig = Omit & { @@ -95,13 +94,14 @@ export const loadHooks = async ( config: ValidConfig ): Promise[]>> => { const hookResults = await Promise.all( - Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { + config.hookInstallations.map(async ({ forHook, options }) => { + const entryPoint = config.hooks[forHook] const hookResult = (await importEntryPoint(Hook, entryPoint)) as Validated return mapValidated(hookResult, (Hook) => { - const schema = HookSchemas[hookName as keyof HookSchemaOptions] - const options = schema ? schema.parse(config.hookOptions[hookName]) : {} - return new Hook(logger, hookName, options) + const schema = HookSchemas[forHook as keyof HookSchemaOptions] + const parsedOptions = schema ? schema.parse(options) : {} + return new Hook(logger, forHook, parsedOptions) }) }) ) @@ -173,7 +173,7 @@ export const createConfig = (): RawConfig => ({ commandTasks: {}, options: {}, hooks: {}, - hookOptions: {} + hookInstallations: [] }) async function asyncFilter(items: T[], predicate: (item: T) => Promise): Promise { @@ -189,7 +189,6 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali const hookConflicts = findConflictingEntries(config.hooks) const taskConflicts = findConflictingEntries(config.tasks) const optionConflicts = findConflicts(Object.values(config.options)) - const hookOptionConflicts = findConflicts(Object.values(config.hookOptions)) const definedCommandTaskConflicts = commandTaskConflicts.filter((conflict) => { return conflict.conflicting[0].id in config.hooks @@ -211,8 +210,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali hookConflicts.length > 0 || definedCommandTaskConflicts.length > 0 || taskConflicts.length > 0 || - optionConflicts.length > 0 || - hookOptionConflicts.length > 0 + optionConflicts.length > 0 ) { shouldThrow = true @@ -231,10 +229,6 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali if (optionConflicts.length) { error.details += formatOptionConflicts(optionConflicts) } - - if (hookOptionConflicts.length) { - error.details += formatHookOptionConflicts(hookOptionConflicts) - } } const configuredCommandTasks = withoutConflicts(Object.values(config.commandTasks)) diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 0cacbacd8..d6f088012 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -2,7 +2,7 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' import type { Hook, Plugin } from '@dotcom-tool-kit/types' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' -import type { HookOptions, EntryPoint, PluginOptions } from './config' +import type { EntryPoint, PluginOptions } from './config' import type { Conflict } from '@dotcom-tool-kit/types/lib/conflict' import type { CommandTask } from './command' @@ -68,23 +68,6 @@ You must resolve this conflict by providing options in your app's Tool Kit confi ` -const formatHookOptionConflict = (conflict: Conflict): string => `${s.plugin( - conflict.conflicting[0].forHook -)}, configured by: -${conflict.conflicting.map((option) => `- ${s.plugin(option.plugin.id)}`)}` - -export const formatHookOptionConflicts = (conflicts: Conflict[]): string => `${s.heading( - 'These plugins have conflicting options for hooks' -)}: - -${conflicts.map(formatHookOptionConflict).join('\n')} - -You must resolve this conflict by providing options in your app's Tool Kit configuration for these hooks, or installing a use-case plugin that provides these options. See ${s.URL( - 'https://github.com/financial-times/dotcom-tool-kit/tree/main/readme.md#hook-options' -)} for more details. - -` - const formatPlugin = (plugin: Plugin): string => plugin.id === 'app root' ? s.app('your app') : `plugin ${s.plugin(plugin.id)}` diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 4c4147d0c..207e374c5 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -9,7 +9,7 @@ import { } from '@dotcom-tool-kit/types' import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' -import { HookOptions, EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' +import { HookInstallation, EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' @@ -274,42 +274,15 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger } } - // load plugin hook options. do this after loading child plugins, so - // parent options get assigned after child options and can override them - for (const [id, configHookOptions] of Object.entries(plugin.rcFile.hooks)) { - // users can specify root options with the dotcom-tool-kit key to mirror - // the name of the root npm package - const existingOptions = config.hookOptions[id] - - const hookOptions: HookOptions = { - options: configHookOptions, - plugin, - forHook: id - } - - if (existingOptions) { - const existingFromDescendent = isDescendent(plugin, existingOptions.plugin) - - // plugins can only override options from their descendents, otherwise it's a conflict - // return a conflict either listing these options and the sibling's, - // or merging in previously-generated options - if (!existingFromDescendent) { - const conflicting = isConflict(existingOptions) ? existingOptions.conflicting : [existingOptions] - - const conflict: Conflict = { - plugin, - conflicting: conflicting.concat(hookOptions) - } - - config.hookOptions[id] = conflict - } else { - // if we're here, any existing options are from a child plugin, - // so merge in overrides from the parent - config.hookOptions[id] = { ...existingOptions, ...hookOptions } + for (const hookEntry of plugin.rcFile.hooks) { + for (const [id, configHookOptions] of Object.entries(hookEntry)) { + const installation: HookInstallation = { + options: configHookOptions, + plugin, + forHook: id } - } else { - // this options key might not have been set yet, in which case use the new one - config.hookOptions[id] = hookOptions + + config.hookInstallations.push(installation) } } } diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index be26f9f70..4ca3d8197 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -5,7 +5,7 @@ import * as path from 'path' import type { Logger } from 'winston' export const explorer = cosmiconfig('toolkit', { ignoreEmptySearchPlaces: false }) -const emptyConfig = { plugins: [], installs: {}, tasks: {}, commands: {}, options: {}, hooks: {} } +const emptyConfig = { plugins: [], installs: {}, tasks: {}, commands: {}, options: {}, hooks: [] } let rootConfig: string | undefined type RawRCFile = { @@ -39,6 +39,6 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo tasks: config.tasks ?? {}, commands: config.commands ?? {}, options: config.options ?? {}, - hooks: config.hooks ?? {} + hooks: config.hooks ?? [] } } diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 5209c5956..5a17e44f7 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -117,7 +117,7 @@ async function main() { tasks: {}, commands: {}, options: {}, - hooks: {} + hooks: [] } const originalCircleConfig = await fsp.readFile(circleConfigPath, 'utf8').catch(() => undefined) diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index e0689879a..a77697da2 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -9,7 +9,7 @@ export type RCFile = { tasks: { [id: string]: string } commands: { [id: string]: string | string[] } options: { [id: string]: Record } - hooks: { [id: string]: Record } + hooks: { [id: string]: Record }[] } export interface Plugin { From f9e81b756cf48bf68eb3a057427e5cd6a05a8e88 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 13 Oct 2023 17:59:57 +0100 Subject: [PATCH 048/321] feat: export CircleCiConfig hook --- plugins/circleci/.toolkitrc.yml | 2 ++ plugins/circleci/src/circleci-config.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index e69de29bb..0d63d15d1 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -0,0 +1,2 @@ +installs: + CircleCiConfig: './lib/circleci-config' diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index a8eb3a17c..a58050bf5 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -242,7 +242,7 @@ const hasJob = (expectedJob: string, jobs: NonNullable): boole (typeof job === 'object' && job.hasOwnProperty(expectedJob)) ) -export default abstract class CircleCiConfigHook extends Hook { +export default abstract class CircleCiConfig extends Hook { installGroup = 'circleci' circleConfigPath = path.resolve(process.cwd(), '.circleci/config.yml') From 800db833c5183cef84c2c03e1140202f03b2a8e6 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 13 Oct 2023 18:14:17 +0100 Subject: [PATCH 049/321] feat: implement options for packagejson hook --- lib/types/src/hooks.ts | 4 +- lib/types/src/schema/hooks/package-json.ts | 7 ++ package-lock.json | 32 +++++++-- plugins/package-json-hook/package.json | 1 + .../src/package-json-helper.ts | 70 +++++++++++-------- 5 files changed, 77 insertions(+), 37 deletions(-) create mode 100644 lib/types/src/schema/hooks/package-json.ts diff --git a/lib/types/src/hooks.ts b/lib/types/src/hooks.ts index 2c3b0b259..678748fb0 100644 --- a/lib/types/src/hooks.ts +++ b/lib/types/src/hooks.ts @@ -1,7 +1,9 @@ import { z } from 'zod' +import { PackageJsonSchema } from './schema/hooks/package-json' + export const HookSchemas = { - 'dummy schema to get types working for now': z.never() + PackageJson: PackageJsonSchema } // Gives the TypeScript type represented by each Schema diff --git a/lib/types/src/schema/hooks/package-json.ts b/lib/types/src/schema/hooks/package-json.ts new file mode 100644 index 000000000..cd25ce6f8 --- /dev/null +++ b/lib/types/src/schema/hooks/package-json.ts @@ -0,0 +1,7 @@ +import { z } from 'zod' + +export const PackageJsonSchema = z.record(z.record(z.union([z.array(z.string()), z.string()]))) + +export type PackageJsonOptions = z.infer + +export const Schema = PackageJsonSchema diff --git a/package-lock.json b/package-lock.json index 6b68ec505..bb3a580ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1189,6 +1189,7 @@ "lib/package-json-hook": { "name": "@dotcom-tool-kit/package-json-hook", "version": "4.2.0", + "extraneous": true, "license": "ISC", "dependencies": { "@financial-times/package-json": "^3.0.0", @@ -1205,11 +1206,6 @@ "npm": "7.x || 8.x || 9.x || 10.x" } }, - "lib/package-json-hook/node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, "lib/state": { "name": "@dotcom-tool-kit/state", "version": "3.3.0", @@ -6293,7 +6289,7 @@ "link": true }, "node_modules/@dotcom-tool-kit/package-json-hook": { - "resolved": "lib/package-json-hook", + "resolved": "plugins/package-json-hook", "link": true }, "node_modules/@dotcom-tool-kit/prettier": { @@ -30125,6 +30121,30 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, + "plugins/package-json-hook": { + "version": "4.2.0", + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/types": "^3.4.0", + "@financial-times/package-json": "^3.0.0", + "lodash": "^4.17.21", + "tslib": "^2.3.1" + }, + "devDependencies": { + "@jest/globals": "^27.4.6", + "@types/lodash": "^4.14.185", + "winston": "^3.5.1" + }, + "engines": { + "node": "16.x || 18.x || 20.x", + "npm": "7.x || 8.x || 9.x || 10.x" + } + }, + "plugins/package-json-hook/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "plugins/prettier": { "name": "@dotcom-tool-kit/prettier", "version": "3.2.0", diff --git a/plugins/package-json-hook/package.json b/plugins/package-json-hook/package.json index 37d925016..5cd96b8bc 100644 --- a/plugins/package-json-hook/package.json +++ b/plugins/package-json-hook/package.json @@ -10,6 +10,7 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/types": "^3.4.0", "@financial-times/package-json": "^3.0.0", "lodash": "^4.17.21", "tslib": "^2.3.1" diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index c0533b060..789fadc00 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -2,32 +2,33 @@ import { z } from 'zod' import { Hook } from '@dotcom-tool-kit/types' import fs from 'fs' import get from 'lodash/get' -import mapValues from 'lodash/mapValues' -import merge from 'lodash/merge' +import set from 'lodash/set' import update from 'lodash/update' import path from 'path' +import { PackageJsonSchema } from '@dotcom-tool-kit/types/lib/schema/hooks/package-json' + interface PackageJsonContents { [field: string]: PackageJsonContents | string } interface PackageJsonStateValue { - hooks: string[] - trailingString: string + commands: string[] + trailingString?: string + installedBy: PackageJson } interface PackageJsonState { - [field: string]: PackageJsonState | PackageJsonStateValue + [path: string]: PackageJsonStateValue } -export default abstract class PackageJson extends Hook { +export default abstract class PackageJson extends Hook { private _packageJson?: PackageJsonContents - abstract field: string | string[] - abstract key: string - abstract hook: string + // Allow some extra characters to be appended to the end of a hooked field. // This is useful if you, for example, need to append the '--' argument // delimiter to commands to allow files to be passed as additional arguments. + // TODO how to handle this with hook options trailingString?: string installGroup = 'package-json' @@ -45,36 +46,45 @@ export default abstract class PackageJson extends Hook { const packageJson = await this.getPackageJson() - return get(packageJson, this.hookPath)?.includes(this.hook) + return Object.entries(this.options).every(([field, object]) => + Object.entries(object).every(([key, command]) => get(packageJson, [field, key])?.includes(command)) + ) } - async install(state?: PackageJsonState): Promise { - state ??= {} - // prepend each hook to maintain the same order as previous implementations - update(state, this.hookPath, (hookState?: PackageJsonStateValue) => ({ - hooks: [this.hook, ...(hookState?.hooks ?? [])], - trailingString: this.trailingString - })) + async install(state: PackageJsonState = {}): Promise { + for (const [field, object] of Object.entries(this.options)) { + for (const [key, command] of Object.entries(object)) { + // prepend each hook to maintain the same order as previous implementations + update( + state, + [field + '.' + key], + (hookState?: PackageJsonStateValue): PackageJsonStateValue => ({ + commands: [...(Array.isArray(command) ? command : [command]), ...(hookState?.commands ?? [])], + installedBy: this, + trailingString: this.trailingString + }) + ) + } + } + return state } async commitInstall(state: PackageJsonState): Promise { - const reduceHooks = (state: PackageJsonState): PackageJsonContents => - mapValues(state, (field) => - Array.isArray(field?.hooks) - ? `dotcom-tool-kit ${field.hooks.join(' ')}${ - field.trailingString ? ' ' + field.trailingString : '' - }` - : reduceHooks(field as PackageJsonState) + const packageJson = await this.getPackageJson() + + for (const [path, installation] of Object.entries(state)) { + set( + packageJson, + path, + `dotcom-tool-kit ${installation.commands.join(' ')}${ + installation.trailingString ? ' ' + installation.trailingString : '' + }` ) + } - const newPackageJson = merge(await this.getPackageJson(), reduceHooks(state)) - await fs.promises.writeFile(this.filepath, JSON.stringify(newPackageJson, null, 2) + '\n') + await fs.promises.writeFile(this.filepath, JSON.stringify(packageJson, null, 2) + '\n') } } From afe8b71436e948f75123338aae5eb1d72da198c8 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 27 Nov 2023 11:51:54 +0000 Subject: [PATCH 050/321] feat: reduce hook installations based on logic from hook classes themselves --- core/cli/src/config.ts | 75 ++++++++++++++++++++++++++------------ core/cli/src/install.ts | 4 +- core/cli/src/plugin.ts | 62 ++++++++++++++++++++++++------- lib/types/src/hook.ts | 38 ++++++++++++++++--- lib/types/src/validated.ts | 8 ++++ 5 files changed, 142 insertions(+), 45 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index ba6eb1158..7a507c13f 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -6,7 +6,7 @@ import type { Logger } from 'winston' import { z } from 'zod' import type { CommandTask } from './command' -import { importEntryPoint, loadPlugin, resolvePlugin } from './plugin' +import { importEntryPoint, loadPlugin, reducePluginHookInstallations, resolvePlugin } from './plugin' import { Conflict, findConflicts, @@ -17,11 +17,14 @@ import { import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' import { + flatMapValidated, Hook, + HookClass, HookConstructor, mapValidated, Plugin, reduceValidated, + sequenceValidated, unwrapValidated, Validated } from '@dotcom-tool-kit/types' @@ -46,12 +49,6 @@ export interface PluginOptions { forPlugin: Plugin } -export interface HookInstallation { - options: Record - plugin: Plugin - forHook: string -} - export interface EntryPoint { plugin: Plugin modulePath: string @@ -65,7 +62,6 @@ export interface RawConfig { commandTasks: { [id: string]: CommandTask | Conflict } options: { [id: string]: PluginOptions | Conflict | undefined } hooks: { [id: string]: EntryPoint | Conflict } - hookInstallations: HookInstallation[] } export type ValidPluginsConfig = Omit & { @@ -89,24 +85,56 @@ export type ValidConfig = Omit[]>> => { - const hookResults = await Promise.all( - config.hookInstallations.map(async ({ forHook, options }) => { - const entryPoint = config.hooks[forHook] - const hookResult = (await importEntryPoint(Hook, entryPoint)) as Validated - - return mapValidated(hookResult, (Hook) => { - const schema = HookSchemas[forHook as keyof HookSchemaOptions] - const parsedOptions = schema ? schema.parse(options) : {} - return new Hook(logger, forHook, parsedOptions) +): Promise>> => { + const hookResultEntries = reduceValidated( + await Promise.all( + Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { + const hookResult = await importEntryPoint(Hook, entryPoint) + return mapValidated(hookResult, (hookClass) => [hookName, hookClass as HookClass] as const) }) - }) + ) + ) + + return mapValidated(hookResultEntries, (hookEntries) => Object.fromEntries(hookEntries)) +} + +export const loadHookInstallations = async ( + logger: Logger, + config: ValidConfig +): Promise[]>> => { + const hookClassResults = await loadHookEntrypoints(logger, config) + const installationResults = await sequenceValidated( + mapValidated(hookClassResults, (hookClasses) => + reducePluginHookInstallations(logger, config, hookClasses, config.plugins['app root']) + ) ) - return reduceValidated(hookResults) + const installationsWithoutConflicts = flatMapValidated(installationResults, (installations) => { + const conflicts = findConflicts(installations) + + if (conflicts.length) { + return { + valid: false, + reasons: [] + } + } + + return { + valid: true, + value: withoutConflicts(installations) + } + }) + + return mapValidated(installationsWithoutConflicts, (installations) => { + return installations.map(({ hookConstructor, forHook, options }) => { + const schema = HookSchemas[forHook as keyof HookSchemaOptions] + const parsedOptions = schema ? schema.parse(options) : {} + return new hookConstructor(logger, forHook, parsedOptions) + }) + }) } export async function fileHash(path: string): Promise { @@ -150,7 +178,7 @@ export async function checkInstall(logger: Logger, config: ValidConfig): Promise return } - const hooks = unwrapValidated(await loadHooks(logger, config), 'hooks are invalid') + const hooks = unwrapValidated(await loadHookInstallations(logger, config), 'hooks are invalid') const uninstalledHooks = await asyncFilter(hooks, async (hook) => { return !(await hook.check()) @@ -172,8 +200,7 @@ export const createConfig = (): RawConfig => ({ tasks: {}, commandTasks: {}, options: {}, - hooks: {}, - hookInstallations: [] + hooks: {} }) async function asyncFilter(items: T[], predicate: (item: T) => Promise): Promise { diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 12ee154d6..ed2234618 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -2,7 +2,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' -import { loadConfig, loadHooks, updateHashes, ValidConfig } from './config' +import { loadConfig, loadHookInstallations, updateHashes, ValidConfig } from './config' import { unwrapValidated } from '@dotcom-tool-kit/types' // implementation of the Array.every method that supports asynchronous predicates @@ -27,7 +27,7 @@ export default async function installHooks(logger: Logger): Promise const errors: Error[] = [] // group hooks without an installGroup separately so that their check() // method runs independently - const hooks = unwrapValidated(await loadHooks(logger, config), 'hooks are invalid') + const hooks = unwrapValidated(await loadHookInstallations(logger, config), 'hooks are invalid') const groups = groupBy(hooks, (hook) => hook.installGroup ?? '__' + hook.id) for (const group of Object.values(groups)) { diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 207e374c5..03fd3419b 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,5 +1,7 @@ import { styles as s } from '@dotcom-tool-kit/logger' import { + HookClass, + HookInstallation, mapValidated, mapValidationError, Plugin, @@ -9,12 +11,13 @@ import { } from '@dotcom-tool-kit/types' import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' -import { HookInstallation, EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' +import { EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig, ValidConfig } from './config' import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' -import { isPlainObject } from 'lodash' +import { groupBy, isPlainObject } from 'lodash' import { Base } from '@dotcom-tool-kit/types/src/base' +import { HookSchemas, Options as HookOptions } from '@dotcom-tool-kit/types/src/hooks' function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { if (!possibleDescendent.parent) { @@ -273,19 +276,52 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger config.options[pluginId] = pluginOptions } } + } - for (const hookEntry of plugin.rcFile.hooks) { - for (const [id, configHookOptions] of Object.entries(hookEntry)) { - const installation: HookInstallation = { - options: configHookOptions, - plugin, - forHook: id - } + config.resolvedPlugins.add(plugin) +} - config.hookInstallations.push(installation) - } - } +export async function reducePluginHookInstallations( + logger: Logger, + config: ValidConfig, + hookClasses: Record, + plugin: Plugin +): Promise<(HookInstallation | Conflict)[]> { + if (!plugin.rcFile) { + return [] } - config.resolvedPlugins.add(plugin) + const rawChildInstallations = await Promise.all( + (plugin.children ?? []).map((child) => reducePluginHookInstallations(logger, config, hookClasses, child)) + ).then((installations) => installations.flat()) + + const childInstallations = Object.entries( + groupBy(rawChildInstallations, (installation) => + isConflict(installation) ? installation.conflicting[0].forHook : installation.forHook + ) + ).flatMap(([forHook, installations]) => { + const hookClass = hookClasses[forHook] + + return hookClass.mergeChildInstallations(plugin, installations) + }) + + if (plugin.rcFile.hooks.length === 0) { + return childInstallations + } + + return plugin.rcFile.hooks.flatMap((hookEntry) => + Object.entries(hookEntry).flatMap(([id, configHookOptions]) => { + const hookClass = hookClasses[id] + const parsedOptions = HookSchemas[id as keyof HookOptions].parse(configHookOptions) + + const installation: HookInstallation = { + options: parsedOptions, + plugin, + forHook: id, + hookConstructor: hookClass + } + + return hookClass.overrideChildInstallations(plugin, installation, childInstallations) + }) + ) } diff --git a/lib/types/src/hook.ts b/lib/types/src/hook.ts index 740680a78..96ce110e5 100644 --- a/lib/types/src/hook.ts +++ b/lib/types/src/hook.ts @@ -2,12 +2,19 @@ import type { Logger } from 'winston' import { Base } from './base' import { hookSymbol, typeSymbol } from './symbols' import { z } from 'zod' +import { Plugin } from './index' +import { Conflict, isConflict } from './conflict' + +export interface HookInstallation { + options: Record + plugin: Plugin + forHook: string + hookConstructor: HookConstructor +} export abstract class Hook extends Base { logger: Logger static description?: string - id: string - options: z.output // This field is used to collect hooks that share state when running their // install methods. All hooks in the same group will run their install method // one after the other, and then their commitInstall method will be run with @@ -22,12 +29,31 @@ export abstract class Hook) { - super() + static mergeChildInstallations( + plugin: Plugin, + childInstallations: (HookInstallation | Conflict)[] + ): (HookInstallation | Conflict)[] { + return [ + { + plugin, + conflicting: childInstallations.flatMap((installation) => + isConflict(installation) ? installation.conflicting : installation + ) + } + ] + } - this.id = id + static overrideChildInstallations( + plugin: Plugin, + parentInstallation: HookInstallation, + _childInstallations: (HookInstallation | Conflict)[] + ): (HookInstallation | Conflict)[] { + return [parentInstallation] + } + + constructor(logger: Logger, public id: string, public options: z.output) { + super() this.logger = logger.child({ hook: this.constructor.name }) - this.options = options } abstract check(): Promise diff --git a/lib/types/src/validated.ts b/lib/types/src/validated.ts index e563e0e1b..1bec4a211 100644 --- a/lib/types/src/validated.ts +++ b/lib/types/src/validated.ts @@ -78,3 +78,11 @@ export function unwrapValidated(validated: Validated, message = ''): T { throw error } } + +export async function sequenceValidated(validated: Validated>): Promise> { + if (validated.valid) { + return { value: await validated.value, valid: true } + } else { + return validated + } +} From d69c4e18d1070dd81fac935b0caaefb84916e25e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 28 Nov 2023 14:45:46 +0000 Subject: [PATCH 051/321] feat: support trailing string in packagejson options --- lib/types/src/schema/hooks/package-json.ts | 13 ++++++++- .../src/package-json-helper.ts | 28 +++++++++++-------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/lib/types/src/schema/hooks/package-json.ts b/lib/types/src/schema/hooks/package-json.ts index cd25ce6f8..13d1f43ce 100644 --- a/lib/types/src/schema/hooks/package-json.ts +++ b/lib/types/src/schema/hooks/package-json.ts @@ -1,6 +1,17 @@ import { z } from 'zod' -export const PackageJsonSchema = z.record(z.record(z.union([z.array(z.string()), z.string()]))) +const CommandListSchema = z.union([z.array(z.string()), z.string()]) +export const PackageJsonSchema = z.record( + z.record( + z.union([ + CommandListSchema, + z.object({ + commands: CommandListSchema, + trailingString: z.string() + }) + ]) + ) +) export type PackageJsonOptions = z.infer diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index 789fadc00..585157e7e 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -22,15 +22,9 @@ interface PackageJsonState { [path: string]: PackageJsonStateValue } -export default abstract class PackageJson extends Hook { +export default class PackageJson extends Hook { private _packageJson?: PackageJsonContents - // Allow some extra characters to be appended to the end of a hooked field. - // This is useful if you, for example, need to append the '--' argument - // delimiter to commands to allow files to be passed as additional arguments. - // TODO how to handle this with hook options - trailingString?: string - installGroup = 'package-json' filepath = path.resolve(process.cwd(), 'package.json') @@ -55,15 +49,27 @@ export default abstract class PackageJson extends Hook { for (const [field, object] of Object.entries(this.options)) { - for (const [key, command] of Object.entries(object)) { - // prepend each hook to maintain the same order as previous implementations + for (const [key, entry] of Object.entries(object)) { + let trailingString: string | undefined + let commands: string[] + + if (Array.isArray(entry)) { + commands = entry + } else if (typeof entry === 'string') { + commands = [entry] + } else { + commands = Array.isArray(entry.commands) ? entry.commands : [entry.commands] + trailingString = entry.trailingString + } + update( state, [field + '.' + key], (hookState?: PackageJsonStateValue): PackageJsonStateValue => ({ - commands: [...(Array.isArray(command) ? command : [command]), ...(hookState?.commands ?? [])], + // prepend each command to maintain the same order as previous implementations + commands: [...commands, ...(hookState?.commands ?? [])], installedBy: this, - trailingString: this.trailingString + trailingString: trailingString }) ) } From a266519952c35278d4ec7b6fc8283eade3b2b19c Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 28 Nov 2023 15:08:22 +0000 Subject: [PATCH 052/321] test: add tests for package json hook options behaviour --- plugins/package-json-hook/test/index.test.ts | 81 ++++++++++++++------ 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 1c82c4100..48b054ee4 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -1,18 +1,12 @@ import { describe, it, expect } from '@jest/globals' import * as path from 'path' import { promises as fs } from 'fs' -import PackageJsonHelper from '../src/package-json-helper' +import PackageJson from '../src/package-json-helper' import winston, { Logger } from 'winston' const logger = (winston as unknown) as Logger describe('package.json hook', () => { - class TestHook extends PackageJsonHelper { - field: string | string[] = 'scripts' - key = 'test-hook' - hook = 'test:hook' - } - const originalDir = process.cwd() afterEach(() => { @@ -22,21 +16,33 @@ describe('package.json hook', () => { describe('check', () => { it('should return true when package.json has hook call in script', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) - const hook = new TestHook(logger, 'TestHook') + const hook = new PackageJson(logger, 'PackageJson', { + scripts: { + 'test-hook': 'test:hook' + } + }) expect(await hook.check()).toBeTruthy() }) it('should return true when script includes other hooks', async () => { process.chdir(path.join(__dirname, 'files', 'multiple-hooks')) - const hook = new TestHook(logger, 'TestHook') + const hook = new PackageJson(logger, 'PackageJson', { + scripts: { + 'test-hook': 'test:hook' + } + }) expect(await hook.check()).toBeTruthy() }) it(`should return false when package.json doesn't have hook call in script`, async () => { process.chdir(path.join(__dirname, 'files', 'without-hook')) - const hook = new TestHook(logger, 'TestHook') + const hook = new PackageJson(logger, 'PackageJson', { + scripts: { + 'test-hook': 'test:hook' + } + }) expect(await hook.check()).toBeFalsy() }) @@ -52,13 +58,23 @@ describe('package.json hook', () => { process.chdir(base) try { - const hook = new TestHook(logger, 'TestHook') + const hook = new PackageJson(logger, 'PackageJson', { + scripts: { + 'test-hook': 'test:hook' + } + }) const state = await hook.install() await hook.commitInstall(state) const packageJson = JSON.parse(await fs.readFile(pkgPath, 'utf-8')) - expect(packageJson).toHaveProperty(['scripts', 'test-hook'], 'dotcom-tool-kit test:hook') + expect(packageJson).toMatchInlineSnapshot(` + Object { + "scripts": Object { + "test-hook": "dotcom-tool-kit test:hook", + }, + } + `) } finally { await fs.writeFile(pkgPath, originalJson) } @@ -73,17 +89,26 @@ describe('package.json hook', () => { process.chdir(base) try { - class TestAppendHook extends TestHook { - trailingString = '--' - } - - const hook = new TestAppendHook(logger, 'TestAppendHook') + const hook = new PackageJson(logger, 'PackageJson', { + scripts: { + 'test-hook': { + trailingString: '--', + commands: 'test:hook' + } + } + }) const state = await hook.install() await hook.commitInstall(state) const packageJson = JSON.parse(await fs.readFile(pkgPath, 'utf-8')) - expect(packageJson).toHaveProperty(['scripts', 'test-hook'], 'dotcom-tool-kit test:hook --') + expect(packageJson).toMatchInlineSnapshot(` + Object { + "scripts": Object { + "test-hook": "dotcom-tool-kit test:hook --", + }, + } + `) } finally { await fs.writeFile(pkgPath, originalJson) } @@ -98,17 +123,25 @@ describe('package.json hook', () => { process.chdir(base) try { - class TestNestedHook extends TestHook { - field = ['scripts', 'nested'] - } - - const hook = new TestNestedHook(logger, 'TestNestedHook') + const hook = new PackageJson(logger, 'PackageJson', { + 'scripts.nested': { + 'test-hook': 'test:hook' + } + }) const state = await hook.install() await hook.commitInstall(state) const packageJson = JSON.parse(await fs.readFile(pkgPath, 'utf-8')) - expect(packageJson).toHaveProperty(['scripts', 'nested', 'test-hook'], 'dotcom-tool-kit test:hook') + expect(packageJson).toMatchInlineSnapshot(` + Object { + "scripts": Object { + "nested": Object { + "test-hook": "dotcom-tool-kit test:hook", + }, + }, + } + `) } finally { await fs.writeFile(pkgPath, originalJson) } From 95181ce14afc77dbe1108fe3b931845669734929 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 5 Dec 2023 16:42:47 +0000 Subject: [PATCH 053/321] refactor: make logic for PackageJson#check more obvious (?) and add a comment that's longer than it --- .../src/package-json-helper.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index 585157e7e..ea498d164 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -42,9 +42,24 @@ export default class PackageJson extends Hook { const packageJson = await this.getPackageJson() - return Object.entries(this.options).every(([field, object]) => - Object.entries(object).every(([key, command]) => get(packageJson, [field, key])?.includes(command)) - ) + + // this instance's `options` is a nested object of expected package.json field/command mappings, e.g. + // { "scripts": { "build": "build:local" } }. in the package.json, they'll have the same structure + // with a `dotcom-tool-kit` CLI prefix, e.g. { "scripts": { "build": "dotcom-tool-kit build:local" } }. + // loop through the nested options object, get the same nested key from package.json, and check that + // field exists, and its string includes the name of the command. if any command from our options is + // missing, the check should fail. + for (const [field, object] of Object.entries(this.options)) { + for (const [key, command] of Object.entries(object)) { + const currentPackageJsonField = get(packageJson, [field, key]) + + if (!currentPackageJsonField || !currentPackageJsonField.includes(command)) { + return false + } + } + } + + return true } async install(state: PackageJsonState = {}): Promise { From f0015b90fc73fe5bb0874fb1c286877158383c59 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 5 Dec 2023 17:19:31 +0000 Subject: [PATCH 054/321] docs: write a thirty-five line comment for a forty-line function --- core/cli/src/plugin.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 03fd3419b..ce7b85f7b 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -281,6 +281,31 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger config.resolvedPlugins.add(plugin) } +// this function recursively collects all the hook installation requests from all plugins, +// and merges them into a single, flat array of HookInstallation objects and/or Conflicts. +// +// it works depth-first (i.e. recurses into child plugins first), and considers how to +// merge options or create conflicts in two stages: 1) when considering all installations +// from child plugins, and 2) when considering how a parent plugin would override its +// children. these steps are separate as a particular parent might not provide an override +// for all its children, and different hooks could expect different ways of resolving +// conflicts. +// +// the actual logic for this is delegated to static methods on Hook classes, +// `Hook.mergeChildInstallations` and `Hook.overrideChildInstallations`, so separate hooks +// can provide different logic for these steps. +// +// the default logic in the base Hook class is to always consider multiple installations +// from child plugins as a conflict, and always consider a installation in a parent as +// completely replacing any installations from children. +// +// for example, for a plugin `p` that depends on children `a`, `b`, and `c` that all provide +// configuration for the `PackageJson` hook, this function will: +// - do all this logic for `a`, `b`, and `c` +// - call `Hook.mergeChildInstallations` with the appropriate concrete Hook class, and +// the resulting installations and/or conflicts from `a`, `b`, and `c` +// - call `Hook.overrideChildInstallations` with the appropriate concrete Hook class, and +// the resulting installations and/or conflicts from `Hook.mergeChildInstallations` and `p` export async function reducePluginHookInstallations( logger: Logger, config: ValidConfig, From a55aee059a261648b2a59e8cefa17a73ffa95660 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 4 Dec 2023 09:30:37 +0000 Subject: [PATCH 055/321] refactor: use chainable methods for validated instead of nested function calls --- core/cli/src/config.ts | 47 +++++-------- core/cli/src/index.ts | 15 ++--- core/cli/src/install.ts | 3 +- core/cli/src/plugin.ts | 87 +++++++++++------------- lib/types/src/base.ts | 34 ++++------ lib/types/src/validated.ts | 131 +++++++++++++++++++++---------------- 6 files changed, 145 insertions(+), 172 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 7a507c13f..6cc58b740 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -16,18 +16,7 @@ import { } from '@dotcom-tool-kit/types/lib/conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' -import { - flatMapValidated, - Hook, - HookClass, - HookConstructor, - mapValidated, - Plugin, - reduceValidated, - sequenceValidated, - unwrapValidated, - Validated -} from '@dotcom-tool-kit/types' +import { Hook, HookClass, invalid, Plugin, reduceValidated, valid, Validated } from '@dotcom-tool-kit/types' import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' import { @@ -93,12 +82,12 @@ const loadHookEntrypoints = async ( await Promise.all( Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { const hookResult = await importEntryPoint(Hook, entryPoint) - return mapValidated(hookResult, (hookClass) => [hookName, hookClass as HookClass] as const) + return hookResult.map((hookClass) => [hookName, hookClass as HookClass] as const) }) ) ) - return mapValidated(hookResultEntries, (hookEntries) => Object.fromEntries(hookEntries)) + return hookResultEntries.map((hookEntries) => Object.fromEntries(hookEntries)) } export const loadHookInstallations = async ( @@ -106,29 +95,23 @@ export const loadHookInstallations = async ( config: ValidConfig ): Promise[]>> => { const hookClassResults = await loadHookEntrypoints(logger, config) - const installationResults = await sequenceValidated( - mapValidated(hookClassResults, (hookClasses) => + const installationResults = await hookClassResults + .map((hookClasses) => reducePluginHookInstallations(logger, config, hookClasses, config.plugins['app root']) ) - ) + .sequence() - const installationsWithoutConflicts = flatMapValidated(installationResults, (installations) => { + const installationsWithoutConflicts = installationResults.flatMap((installations) => { const conflicts = findConflicts(installations) if (conflicts.length) { - return { - valid: false, - reasons: [] - } + return invalid<[]>([]) } - return { - valid: true, - value: withoutConflicts(installations) - } + return valid(withoutConflicts(installations)) }) - return mapValidated(installationsWithoutConflicts, (installations) => { + return installationsWithoutConflicts.map((installations) => { return installations.map(({ hookConstructor, forHook, options }) => { const schema = HookSchemas[forHook as keyof HookSchemaOptions] const parsedOptions = schema ? schema.parse(options) : {} @@ -178,7 +161,7 @@ export async function checkInstall(logger: Logger, config: ValidConfig): Promise return } - const hooks = unwrapValidated(await loadHookInstallations(logger, config), 'hooks are invalid') + const hooks = (await loadHookInstallations(logger, config)).unwrap('hooks are invalid') const uninstalledHooks = await asyncFilter(hooks, async (hook) => { return !(await hook.check()) @@ -344,9 +327,9 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali export function validatePlugins(config: RawConfig): Validated { const validatedPlugins = reduceValidated( - Object.entries(config.plugins).map(([id, plugin]) => mapValidated(plugin, (p) => [id, p] as const)) + Object.entries(config.plugins).map(([id, plugin]) => plugin.map((p) => [id, p] as const)) ) - return mapValidated(validatedPlugins, (plugins) => ({ ...config, plugins: Object.fromEntries(plugins) })) + return validatedPlugins.map((plugins) => ({ ...config, plugins: Object.fromEntries(plugins) })) } export function loadConfig(logger: Logger, options?: { validate?: true }): Promise @@ -357,10 +340,10 @@ export async function loadConfig(logger: Logger, { validate = true } = {}): Prom // start loading config and child plugins, starting from the consumer app directory const rootPlugin = await loadPlugin('app root', config, logger) - const validRootPlugin = unwrapValidated(rootPlugin, 'root plugin was not valid!') + const validRootPlugin = rootPlugin.unwrap('root plugin was not valid!') const validatedPluginConfig = validatePlugins(config) - const validPluginConfig = unwrapValidated(validatedPluginConfig, 'config was not valid!') + const validPluginConfig = validatedPluginConfig.unwrap('config was not valid!') // collate root plugin and descendent hooks, options etc into config resolvePlugin(validRootPlugin, validPluginConfig, logger) diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 2156a9497..84b6e6be8 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -5,14 +5,7 @@ import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' import util from 'util' import { formatPluginTree } from './messages' -import { - Task, - TaskConstructor, - Validated, - mapValidated, - reduceValidated, - unwrapValidated -} from '@dotcom-tool-kit/types' +import { Task, TaskConstructor, Validated, reduceValidated } from '@dotcom-tool-kit/types' import { importEntryPoint } from './plugin' type ErrorSummary = { @@ -47,7 +40,7 @@ const loadTasks = async ( const entryPoint = config.tasks[taskName] const taskResult = await importEntryPoint(Task, entryPoint) - return mapValidated(taskResult, (Task) => [ + return taskResult.map((Task) => [ taskName, new ((Task as unknown) as TaskConstructor)( logger, @@ -58,7 +51,7 @@ const loadTasks = async ( }) ) - return mapValidated(reduceValidated(taskResults), Object.fromEntries) + return reduceValidated(taskResults).map(Object.fromEntries) } export async function runTasks(logger: Logger, hooks: string[], files?: string[]): Promise { @@ -93,7 +86,7 @@ ${availableHooks}` } const taskNames = hooks.flatMap((hook) => config.commandTasks[hook]?.tasks ?? []) - const tasks = unwrapValidated(await loadTasks(logger, taskNames, config), 'tasks are invalid') + const tasks = (await loadTasks(logger, taskNames, config)).unwrap('tasks are invalid') for (const hook of hooks) { const errors: ErrorSummary[] = [] diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index ed2234618..2ceb3f49d 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -3,7 +3,6 @@ import { OptionKey, setOptions } from '@dotcom-tool-kit/options' import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' import { loadConfig, loadHookInstallations, updateHashes, ValidConfig } from './config' -import { unwrapValidated } from '@dotcom-tool-kit/types' // implementation of the Array.every method that supports asynchronous predicates async function asyncEvery(arr: T[], pred: (x: T) => Promise): Promise { @@ -27,7 +26,7 @@ export default async function installHooks(logger: Logger): Promise const errors: Error[] = [] // group hooks without an installGroup separately so that their check() // method runs independently - const hooks = unwrapValidated(await loadHookInstallations(logger, config), 'hooks are invalid') + const hooks = (await loadHookInstallations(logger, config)).unwrap('hooks are invalid') const groups = groupBy(hooks, (hook) => hook.installGroup ?? '__' + hook.id) for (const group of Object.values(groups)) { diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index ce7b85f7b..2d3914f59 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -2,11 +2,10 @@ import { styles as s } from '@dotcom-tool-kit/logger' import { HookClass, HookInstallation, - mapValidated, - mapValidationError, + invalid, Plugin, reduceValidated, - Valid, + valid, Validated } from '@dotcom-tool-kit/types' import resolvePkg from 'resolve-pkg' @@ -40,14 +39,11 @@ export async function importEntryPoint [ - `the ${type.name.toLowerCase()} ${s.hook(name)} is not a compatible instance of ${s.code( - type.name - )}:\n - ${reasons.join('\n - ')}` - ]) + return type + .isCompatible(pluginModule.default) + .mapError((reasons) => [ + `the ${type.name.toLowerCase()} ${s.hook(name)} is not a compatible instance of ${s.code( + type.name + )}:\n - ${reasons.join('\n - ')}` + ]) } else { - return { - valid: false, - reasons: [ - `entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( - entryPoint.plugin.id - )} does not have a ${s.code('default')} export` - ] - } + return invalid([ + `entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( + entryPoint.plugin.id + )} does not have a ${s.code('default')} export` + ]) } } @@ -108,37 +100,34 @@ export async function loadPlugin( const root = parent ? parent.root : process.cwd() const pluginRoot = isAppRoot ? root : resolvePkg(id, { cwd: root }) if (!pluginRoot) { - return { valid: false, reasons: [`could not find path for name ${s.filepath(id)}`] } + return invalid([`could not find path for name ${s.filepath(id)}`]) } - const plugin: Valid = { - valid: true, - value: { - id, - root: pluginRoot, - parent - } + const plugin = { + id, + root: pluginRoot, + parent, + rcFile: await loadToolKitRC(logger, pluginRoot, isAppRoot), + children: [] as Plugin[] } - config.plugins[id] = plugin - - // ESlint disable explanation: erroring due to a possible race condition but is a false positive since the plugin variable isn't from another scope and can't be written to concurrently. + // ESlint disable explanation: erroring due to a possible race condition but is a false positive since the config variable isn't from another scope and can't be written to concurrently. // eslint-disable-next-line require-atomic-updates - plugin.value.rcFile = await loadToolKitRC(logger, pluginRoot, isAppRoot) + config.plugins[id] = valid(plugin) const children = await Promise.all( - plugin.value.rcFile.plugins.map((child) => loadPlugin(child, config, logger, plugin.value)) + plugin.rcFile.plugins.map((child) => loadPlugin(child, config, logger, plugin)) ) - const validatedChildren = mapValidationError(reduceValidated(children), (reasons) => [ + const validatedChildren = reduceValidated(children).mapError((reasons) => [ indentReasons(`some child plugins of ${s.plugin(id)} failed to load:\n- ${reasons.join('\n- ')}`) ]) - return mapValidated(validatedChildren, (children) => { + return validatedChildren.map((children) => { // avoid cloning the plugin value with an object spread as we do object // reference comparisons in multiple places - plugin.value.children = children - return plugin.value + plugin.children = children + return plugin }) } diff --git a/lib/types/src/base.ts b/lib/types/src/base.ts index ef73f5ec2..70e267707 100644 --- a/lib/types/src/base.ts +++ b/lib/types/src/base.ts @@ -2,7 +2,7 @@ import { styles as s } from '@dotcom-tool-kit/logger' import path from 'path' import fs from 'fs' import { baseSymbol, typeSymbol } from './symbols' -import { Validated } from './validated' +import { Validated, invalid, valid } from './validated' import semver from 'semver' const packageJsonPath = path.resolve(__dirname, '../package.json') @@ -28,16 +28,13 @@ export abstract class Base { static isCompatible(objectToCheck: unknown): Validated { if (!this.is(objectToCheck)) { - return { - valid: false, - reasons: [ - `${s.plugin( - '@dotcom-tool-kit/types' - )} type symbol is missing, make sure that this object derives from the ${s.code( - 'Task' - )} or ${s.code('Hook')} class defined by the plugin` - ] - } + return invalid([ + `${s.plugin( + '@dotcom-tool-kit/types' + )} type symbol is missing, make sure that this object derives from the ${s.code('Task')} or ${s.code( + 'Hook' + )} class defined by the plugin` + ]) } // an 'objectToCheck' from a plugin is compatible with this CLI if its @@ -49,16 +46,13 @@ export abstract class Base { // that depends on any higher minor version of types. const range = `^${this.version}` if (semver.satisfies(objectToCheck.version, range)) { - return { valid: true, value: objectToCheck as T } + return valid(objectToCheck as T) } else { - return { - valid: false, - reasons: [ - `object is from an outdated version of ${s.plugin( - '@dotcom-tool-kit/types' - )}, make sure you're using at least version ${s.heading(this.version)} of the plugin` - ] - } + return invalid([ + `object is from an outdated version of ${s.plugin( + '@dotcom-tool-kit/types' + )}, make sure you're using at least version ${s.heading(this.version)} of the plugin` + ]) } } } diff --git a/lib/types/src/validated.ts b/lib/types/src/validated.ts index 1bec4a211..e13039c7a 100644 --- a/lib/types/src/validated.ts +++ b/lib/types/src/validated.ts @@ -1,58 +1,99 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -export interface Invalid { +interface Mixin { + map(f: (val: T) => U): Validated + mapError(f: (reasons: string[]) => string[]): Validated + flatMap(f: (val: T) => Validated): Validated + join(other: Validated): Validated<[T, U]> + sequence(): Promise>> + unwrap(message?: string): T +} + +export type Invalid = { valid: false reasons: string[] } -export interface Valid { + +export type Valid = { valid: true value: T } -export type Validated = Invalid | Valid -export function mapValidated(validated: Validated, f: (val: T) => U): Validated { - if (validated.valid) { - return { valid: true, value: f(validated.value) } - } else { - return validated - } -} +export type Validated = (Invalid | Valid) & Mixin -export function mapValidationError( - validated: Validated, - f: (reasons: string[]) => string[] -): Validated { - if (validated.valid) { - return validated - } else { - return { valid: false, reasons: f(validated.reasons) } - } -} +export const invalid = (reasons: string[]) => mixin({ valid: false, reasons }) +export const valid = (value: T) => mixin({ valid: true, value }) + +const mixin = (validated: Invalid | Valid): Validated => ({ + ...validated, + + map(f) { + if (validated.valid) { + return valid(f(validated.value)) + } else { + return invalid(validated.reasons) + } + }, -export function joinValidated(first: Validated, second: Validated): Validated<[T, U]> { - if (first.valid) { - if (second.valid) { - return { valid: true, value: [first.value, second.value] } + mapError(f) { + if (validated.valid) { + return mixin(validated) } else { - return second + return invalid(f(validated.reasons)) } - } else { - if (second.valid) { - return first + }, + + flatMap(f) { + if (validated.valid) { + return f(validated.value) } else { - return { valid: false, reasons: [...first.reasons, ...second.reasons] } + return mixin(validated) + } + }, + + join(other: Validated) { + if (validated.valid) { + if (other.valid) { + return valid([validated.value, other.value]) + } else { + return invalid<[T, U]>(other.reasons) + } + } else { + if (other.valid) { + return mixin<[T, U]>(validated) + } else { + return invalid<[T, U]>([...validated.reasons, ...other.reasons]) + } + } + }, + + unwrap(message = '') { + if (validated.valid) { + return validated.value + } else { + const error = new ToolKitError(message) + error.details = validated.reasons.join('\n\n') + throw error + } + }, + + async sequence() { + if (validated.valid) { + return valid(await validated.value) + } else { + return invalid(validated.reasons) } } -} +}) export function reduceValidated(validated: Validated[]): Validated { - let sequenced: Validated = { valid: true, value: [] } + let sequenced: Validated = valid([]) for (const val of validated) { if (sequenced.valid) { if (val.valid) { sequenced.value.push(val.value) } else { - sequenced = { valid: false, reasons: val.reasons } + sequenced = invalid(val.reasons) } } else if (!val.valid) { sequenced.reasons.push(...val.reasons) @@ -60,29 +101,3 @@ export function reduceValidated(validated: Validated[]): Validated { } return sequenced } - -export function flatMapValidated(validated: Validated, f: (val: T) => Validated): Validated { - if (validated.valid) { - return f(validated.value) - } else { - return validated - } -} - -export function unwrapValidated(validated: Validated, message = ''): T { - if (validated.valid) { - return validated.value - } else { - const error = new ToolKitError(message) - error.details = validated.reasons.join('\n\n') - throw error - } -} - -export async function sequenceValidated(validated: Validated>): Promise> { - if (validated.valid) { - return { value: await validated.value, valid: true } - } else { - return validated - } -} From 736abce1f037c395f58ffbdb3065378541054105 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 4 Dec 2023 16:14:38 +0000 Subject: [PATCH 056/321] refactor: rename Validated.sequence to .awaitValue --- core/cli/src/config.ts | 2 +- lib/types/src/validated.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 6cc58b740..6a4c19556 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -99,7 +99,7 @@ export const loadHookInstallations = async ( .map((hookClasses) => reducePluginHookInstallations(logger, config, hookClasses, config.plugins['app root']) ) - .sequence() + .awaitValue() const installationsWithoutConflicts = installationResults.flatMap((installations) => { const conflicts = findConflicts(installations) diff --git a/lib/types/src/validated.ts b/lib/types/src/validated.ts index e13039c7a..f94f2d17e 100644 --- a/lib/types/src/validated.ts +++ b/lib/types/src/validated.ts @@ -5,7 +5,7 @@ interface Mixin { mapError(f: (reasons: string[]) => string[]): Validated flatMap(f: (val: T) => Validated): Validated join(other: Validated): Validated<[T, U]> - sequence(): Promise>> + awaitValue(): Promise>> unwrap(message?: string): T } @@ -77,7 +77,7 @@ const mixin = (validated: Invalid | Valid): Validated => ({ } }, - async sequence() { + async awaitValue() { if (validated.valid) { return valid(await validated.value) } else { From 8209b504ed4a689bd88c19e11c72f3909cd5d6b1 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 4 Dec 2023 16:15:22 +0000 Subject: [PATCH 057/321] style: kara can have little a method chaining, as a treat --- core/cli/src/plugin.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 2d3914f59..803a11015 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -119,16 +119,16 @@ export async function loadPlugin( plugin.rcFile.plugins.map((child) => loadPlugin(child, config, logger, plugin)) ) - const validatedChildren = reduceValidated(children).mapError((reasons) => [ - indentReasons(`some child plugins of ${s.plugin(id)} failed to load:\n- ${reasons.join('\n- ')}`) - ]) - - return validatedChildren.map((children) => { - // avoid cloning the plugin value with an object spread as we do object - // reference comparisons in multiple places - plugin.children = children - return plugin - }) + return reduceValidated(children) + .mapError((reasons) => [ + indentReasons(`some child plugins of ${s.plugin(id)} failed to load:\n- ${reasons.join('\n- ')}`) + ]) + .map((children) => { + // avoid cloning the plugin value with an object spread as we do object + // reference comparisons in multiple places + plugin.children = children + return plugin + }) } export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger: Logger): void { From 3eff1cfb60578614a9d89c21d8c12da9e3659478 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 14 Dec 2023 14:30:13 +0000 Subject: [PATCH 058/321] fix: check ids for resolved plugins not plugin options we already have the convention that plugins with the same ids are the same plugins so --- core/cli/src/config.ts | 2 +- core/cli/src/plugin.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 6a4c19556..28a15337a 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -46,7 +46,7 @@ export interface EntryPoint { export interface RawConfig { root: string plugins: { [id: string]: Validated } - resolvedPlugins: Set + resolvedPlugins: Set tasks: { [id: string]: EntryPoint | Conflict } commandTasks: { [id: string]: CommandTask | Conflict } options: { [id: string]: PluginOptions | Conflict | undefined } diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 803a11015..6473918ca 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -134,7 +134,7 @@ export async function loadPlugin( export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger: Logger): void { // don't resolve plugins that have already been resolved to prevent self-conflicts // between plugins included at multiple points in the tree - if (config.resolvedPlugins.has(plugin)) { + if (config.resolvedPlugins.has(plugin.id)) { return } @@ -267,7 +267,7 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger } } - config.resolvedPlugins.add(plugin) + config.resolvedPlugins.add(plugin.id) } // this function recursively collects all the hook installation requests from all plugins, From a3db11acfb7f529f0e138543f3b35e5577a634e1 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 18 Dec 2023 10:02:23 +0000 Subject: [PATCH 059/321] refactor!: rename Hook#check to Hook#isInstalled --- core/cli/src/config.ts | 2 +- core/cli/src/install.ts | 4 ++-- docs/custom-plugins.md | 6 +++--- docs/developing-tool-kit.md | 4 ++-- lib/types/src/hook.ts | 2 +- plugins/circleci/src/circleci-config.ts | 2 +- plugins/circleci/test/circleci-config.test.ts | 6 +++--- plugins/package-json-hook/src/package-json-helper.ts | 2 +- plugins/package-json-hook/test/index.test.ts | 6 +++--- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 28a15337a..0d184519f 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -164,7 +164,7 @@ export async function checkInstall(logger: Logger, config: ValidConfig): Promise const hooks = (await loadHookInstallations(logger, config)).unwrap('hooks are invalid') const uninstalledHooks = await asyncFilter(hooks, async (hook) => { - return !(await hook.check()) + return !(await hook.isInstalled()) }) if (uninstalledHooks.length > 0) { diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 2ceb3f49d..ee10224b9 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -31,8 +31,8 @@ export default async function installHooks(logger: Logger): Promise const groups = groupBy(hooks, (hook) => hook.installGroup ?? '__' + hook.id) for (const group of Object.values(groups)) { try { - const allChecksPassed = await asyncEvery(group, (hook) => hook.check()) - if (!allChecksPassed) { + const allHooksInstalled = await asyncEvery(group, (hook) => hook.isInstalled()) + if (!allHooksInstalled) { let state = undefined for (const hook of group) { state = await hook.install(state) diff --git a/docs/custom-plugins.md b/docs/custom-plugins.md index 66ab38efb..6ab9f3c2c 100644 --- a/docs/custom-plugins.md +++ b/docs/custom-plugins.md @@ -79,13 +79,13 @@ A Hook defines an abstract label to run tasks with, as well as managing where in This abstraction lets us write different plugins for defining tasks to be run, separate from the plugins defining where they should be run from, whilst maintaining the link between them. We've already seen that `build:ci` could be running Rollup, or Webpack, or any other task; in addition, `build:ci` itself could be defined by a different plugin, such as a Github Actions plugin, that would automatically manage configuration in `.github/workflows`. -The automatic configuration management is implemented by `Hook` subclasses. These define a `check` method that should return `true` if the hook is correctly installed in the repository or `false` if it needs installing, and an `install` method to actually perform the installation. Every time Tool Kit runs, it checks that every hook is installed in your repo, and if any aren't, it exits with an error (to ensure the repo is always consistent with what it expects). You can then run `dotcom-tool-kit --install` to run the installation of every hook that isn't installed. +The automatic configuration management is implemented by `Hook` subclasses. These define an `isInstalled` method that should return `true` if the hook is correctly installed in the repository or `false` if it needs installing, and an `install` method to actually perform the installation. Every time Tool Kit runs, it checks that every hook is installed in your repo, and if any aren't, it exits with an error (to ensure the repo is always consistent with what it expects). You can then run `dotcom-tool-kit --install` to run the installation of every hook that isn't installed. If you find yourself asking a question like "how do I run a Tool Kit task from a different npm script", **you should implement a hook** to allow Tool Kit to automatically manage that configuration for any new repos using your plugin, rather than expecting new users to add that configuration themselves when installing the plugin. Hooks have a loose naming convention of `category:environment`. This is only meant for humans to be able to intuitively understand which hooks are related; it's not required by the Tool Kit core itself. -Let's say you want to run some task on the npm `prepare` script (which automatically runs after `npm install` and before `npm publish`). We'll call that hook `prepare:local`, and the plugin will live in `toolkit/npm-prepare` ([structured as above](#common-plugin-structure)). Create a subclass of the `Hook` class from `@dotcom-tool-kit/types`, implement the `check` and `install` methods, and export a `hooks` object to map it to the name we're giving it. Your `toolkit/npm-prepare/index.js` might include: +Let's say you want to run some task on the npm `prepare` script (which automatically runs after `npm install` and before `npm publish`). We'll call that hook `prepare:local`, and the plugin will live in `toolkit/npm-prepare` ([structured as above](#common-plugin-structure)). Create a subclass of the `Hook` class from `@dotcom-tool-kit/types`, implement the `isInstalled` and `install` methods, and export a `hooks` object to map it to the name we're giving it. Your `toolkit/npm-prepare/index.js` might include: ```js const { Hook } = require('@dotcom-tool-kit/types') @@ -101,7 +101,7 @@ class PrepareHook extends Hook { return this._packageJson } - async check() { + async isInstalled() { return this.packageJson.getField('scripts')?.prepare === 'dotcom-tool-kit prepare:local' } diff --git a/docs/developing-tool-kit.md b/docs/developing-tool-kit.md index c1f2aa6a4..2ba3a0ac7 100644 --- a/docs/developing-tool-kit.md +++ b/docs/developing-tool-kit.md @@ -58,7 +58,7 @@ Tasks won't be usable by your plugin's users unless you export them from the ent A hook ensures a repo using Tool Kit has the relevant configuration to run things from Tool Kit. -A hook extends the `Hook` class from `@dotcom-tool-kit/types`, implementing its abstract asynchronous `check` and `install` functions. You also need to write a helpful `description` field, which will be displayed in the `--help` text. +A hook extends the `Hook` class from `@dotcom-tool-kit/types`, implementing its abstract asynchronous `isInstalled` and `install` functions. You also need to write a helpful `description` field, which will be displayed in the `--help` text. ```typescript import { Hook } from '@dotcom-tool-kit/types' @@ -66,7 +66,7 @@ import { Hook } from '@dotcom-tool-kit/types' export default NpmRunTest extends Hook { static description = 'hook to run tasks with `npm run test`' - async check(): Promise { + async isInstalled(): Promise { // return true if the `test` script is correctly defined in `package.json` } diff --git a/lib/types/src/hook.ts b/lib/types/src/hook.ts index 96ce110e5..c63fb79a7 100644 --- a/lib/types/src/hook.ts +++ b/lib/types/src/hook.ts @@ -56,7 +56,7 @@ export abstract class Hook + abstract isInstalled(): Promise abstract install(state?: State): Promise async commitInstall(_state: State): Promise { return diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index a58050bf5..0897023cf 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -267,7 +267,7 @@ export default abstract class CircleCiConfig extends Hook { + async isInstalled(): Promise { const rawConfig = await this.getCircleConfig() if (!rawConfig) { return false diff --git a/plugins/circleci/test/circleci-config.test.ts b/plugins/circleci/test/circleci-config.test.ts index f64da6c30..a2a447c86 100644 --- a/plugins/circleci/test/circleci-config.test.ts +++ b/plugins/circleci/test/circleci-config.test.ts @@ -56,13 +56,13 @@ describe('CircleCI config hook', () => { it('should return true if the hook job is in the circleci workflow', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) const hook = new TestHook(logger, 'TestHook') - expect(await hook.check()).toBeTruthy() + expect(await hook.isInstalled()).toBeTruthy() }) it('should return false if the hook job is not in the circleci workflow', async () => { process.chdir(path.join(__dirname, 'files', 'without-hook')) const hook = new TestHook(logger, 'TestHook') - expect(await hook.check()).toBeFalsy() + expect(await hook.isInstalled()).toBeFalsy() }) it('should return false if the base configuration is missing', async () => { @@ -71,7 +71,7 @@ describe('CircleCI config hook', () => { // reset field overridden by FakeCircleCiConfigHook so that we do check // for the base config hook.haveCheckedBaseConfig = false - expect(await hook.check()).toBeFalsy() + expect(await hook.isInstalled()).toBeFalsy() }) }) diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index ea498d164..573542111 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -40,7 +40,7 @@ export default class PackageJson extends Hook { + async isInstalled(): Promise { const packageJson = await this.getPackageJson() // this instance's `options` is a nested object of expected package.json field/command mappings, e.g. diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 48b054ee4..7df60062e 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -22,7 +22,7 @@ describe('package.json hook', () => { } }) - expect(await hook.check()).toBeTruthy() + expect(await hook.isInstalled()).toBeTruthy() }) it('should return true when script includes other hooks', async () => { @@ -33,7 +33,7 @@ describe('package.json hook', () => { } }) - expect(await hook.check()).toBeTruthy() + expect(await hook.isInstalled()).toBeTruthy() }) it(`should return false when package.json doesn't have hook call in script`, async () => { @@ -44,7 +44,7 @@ describe('package.json hook', () => { } }) - expect(await hook.check()).toBeFalsy() + expect(await hook.isInstalled()).toBeFalsy() }) }) From e8fca2ccbc152618ca45716a05fe94b5e07089b8 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 11:00:49 +0000 Subject: [PATCH 060/321] refactor: move reducePluginHookInstallations to its own module --- core/cli/src/config.ts | 3 +- core/cli/src/plugin.ts | 85 +-------------------- core/cli/src/plugin/reduce-installations.ts | 77 +++++++++++++++++++ 3 files changed, 82 insertions(+), 83 deletions(-) create mode 100644 core/cli/src/plugin/reduce-installations.ts diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 0d184519f..834622166 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -6,7 +6,7 @@ import type { Logger } from 'winston' import { z } from 'zod' import type { CommandTask } from './command' -import { importEntryPoint, loadPlugin, reducePluginHookInstallations, resolvePlugin } from './plugin' +import { importEntryPoint, loadPlugin, resolvePlugin } from './plugin' import { Conflict, findConflicts, @@ -31,6 +31,7 @@ import { formatMissingTasks, formatInvalidOptions } from './messages' +import { reducePluginHookInstallations } from './plugin/reduce-installations' export interface PluginOptions { options: Record diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 6473918ca..0d46bcbf1 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,22 +1,13 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import { - HookClass, - HookInstallation, - invalid, - Plugin, - reduceValidated, - valid, - Validated -} from '@dotcom-tool-kit/types' +import { invalid, Plugin, reduceValidated, valid, Validated } from '@dotcom-tool-kit/types' import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' -import { EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig, ValidConfig } from './config' +import { EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' -import { groupBy, isPlainObject } from 'lodash' +import { isPlainObject } from 'lodash' import { Base } from '@dotcom-tool-kit/types/src/base' -import { HookSchemas, Options as HookOptions } from '@dotcom-tool-kit/types/src/hooks' function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { if (!possibleDescendent.parent) { @@ -269,73 +260,3 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger config.resolvedPlugins.add(plugin.id) } - -// this function recursively collects all the hook installation requests from all plugins, -// and merges them into a single, flat array of HookInstallation objects and/or Conflicts. -// -// it works depth-first (i.e. recurses into child plugins first), and considers how to -// merge options or create conflicts in two stages: 1) when considering all installations -// from child plugins, and 2) when considering how a parent plugin would override its -// children. these steps are separate as a particular parent might not provide an override -// for all its children, and different hooks could expect different ways of resolving -// conflicts. -// -// the actual logic for this is delegated to static methods on Hook classes, -// `Hook.mergeChildInstallations` and `Hook.overrideChildInstallations`, so separate hooks -// can provide different logic for these steps. -// -// the default logic in the base Hook class is to always consider multiple installations -// from child plugins as a conflict, and always consider a installation in a parent as -// completely replacing any installations from children. -// -// for example, for a plugin `p` that depends on children `a`, `b`, and `c` that all provide -// configuration for the `PackageJson` hook, this function will: -// - do all this logic for `a`, `b`, and `c` -// - call `Hook.mergeChildInstallations` with the appropriate concrete Hook class, and -// the resulting installations and/or conflicts from `a`, `b`, and `c` -// - call `Hook.overrideChildInstallations` with the appropriate concrete Hook class, and -// the resulting installations and/or conflicts from `Hook.mergeChildInstallations` and `p` -export async function reducePluginHookInstallations( - logger: Logger, - config: ValidConfig, - hookClasses: Record, - plugin: Plugin -): Promise<(HookInstallation | Conflict)[]> { - if (!plugin.rcFile) { - return [] - } - - const rawChildInstallations = await Promise.all( - (plugin.children ?? []).map((child) => reducePluginHookInstallations(logger, config, hookClasses, child)) - ).then((installations) => installations.flat()) - - const childInstallations = Object.entries( - groupBy(rawChildInstallations, (installation) => - isConflict(installation) ? installation.conflicting[0].forHook : installation.forHook - ) - ).flatMap(([forHook, installations]) => { - const hookClass = hookClasses[forHook] - - return hookClass.mergeChildInstallations(plugin, installations) - }) - - if (plugin.rcFile.hooks.length === 0) { - return childInstallations - } - - return plugin.rcFile.hooks.flatMap((hookEntry) => - Object.entries(hookEntry).flatMap(([id, configHookOptions]) => { - const hookClass = hookClasses[id] - const parsedOptions = HookSchemas[id as keyof HookOptions].parse(configHookOptions) - - const installation: HookInstallation = { - options: parsedOptions, - plugin, - forHook: id, - hookConstructor: hookClass - } - - return hookClass.overrideChildInstallations(plugin, installation, childInstallations) - }) - ) -} diff --git a/core/cli/src/plugin/reduce-installations.ts b/core/cli/src/plugin/reduce-installations.ts new file mode 100644 index 000000000..f38412a4a --- /dev/null +++ b/core/cli/src/plugin/reduce-installations.ts @@ -0,0 +1,77 @@ +import { Logger } from 'winston' +import { ValidConfig } from '../config' +import { HookClass, HookInstallation, Plugin } from '@dotcom-tool-kit/types' +import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { groupBy } from 'lodash' +import { HookSchemas, Options as HookOptions } from '@dotcom-tool-kit/types/src/hooks' + +// this function recursively collects all the hook installation requests from all plugins, +// and merges them into a single, flat array of HookInstallation objects and/or Conflicts. +// +// it works depth-first (i.e. recurses into child plugins first), and considers how to +// merge options or create conflicts in two stages: 1) when considering all installations +// from child plugins, and 2) when considering how a parent plugin would override its +// children. these steps are separate as a particular parent might not provide an override +// for all its children, and different hooks could expect different ways of resolving +// conflicts. +// +// the actual logic for this is delegated to static methods on Hook classes, +// `Hook.mergeChildInstallations` and `Hook.overrideChildInstallations`, so separate hooks +// can provide different logic for these steps. +// +// the default logic in the base Hook class is to always consider multiple installations +// from child plugins as a conflict, and always consider a installation in a parent as +// completely replacing any installations from children. +// +// for example, for a plugin `p` that depends on children `a`, `b`, and `c` that all provide +// configuration for the `PackageJson` hook, this function will: +// - do all this logic for `a`, `b`, and `c` +// - call `Hook.mergeChildInstallations` with the appropriate concrete Hook class, and +// the resulting installations and/or conflicts from `a`, `b`, and `c` +// - call `Hook.overrideChildInstallations` with the appropriate concrete Hook class, and + +// the resulting installations and/or conflicts from `Hook.mergeChildInstallations` and `p` +export async function reducePluginHookInstallations( + logger: Logger, + config: ValidConfig, + hookClasses: Record, + plugin: Plugin +): Promise<(HookInstallation | Conflict)[]> { + if (!plugin.rcFile) { + return [] + } + + const rawChildInstallations = await Promise.all( + (plugin.children ?? []).map((child) => reducePluginHookInstallations(logger, config, hookClasses, child)) + ).then((installations) => installations.flat()) + + const childInstallations = Object.entries( + groupBy(rawChildInstallations, (installation) => + isConflict(installation) ? installation.conflicting[0].forHook : installation.forHook + ) + ).flatMap(([forHook, installations]) => { + const hookClass = hookClasses[forHook] + + return hookClass.mergeChildInstallations(plugin, installations) + }) + + if (plugin.rcFile.hooks.length === 0) { + return childInstallations + } + + return plugin.rcFile.hooks.flatMap((hookEntry) => + Object.entries(hookEntry).flatMap(([id, configHookOptions]) => { + const hookClass = hookClasses[id] + const parsedOptions = HookSchemas[id as keyof HookOptions].parse(configHookOptions) + + const installation: HookInstallation = { + options: parsedOptions, + plugin, + forHook: id, + hookConstructor: hookClass + } + + return hookClass.overrideChildInstallations(plugin, installation, childInstallations) + }) + ) +} From 0e00268bd0917c1847f9f2cb2f3a7418009d2988 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 11:06:55 +0000 Subject: [PATCH 061/321] refactor: move config hashing stuff to own module --- core/cli/src/config.ts | 41 +------------------------------------ core/cli/src/config/hash.ts | 40 ++++++++++++++++++++++++++++++++++++ core/cli/src/install.ts | 3 ++- 3 files changed, 43 insertions(+), 41 deletions(-) create mode 100644 core/cli/src/config/hash.ts diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 834622166..2381fcafe 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -1,6 +1,3 @@ -import { createHash } from 'node:crypto' -import { readFile } from 'node:fs/promises' - import path from 'path' import type { Logger } from 'winston' import { z } from 'zod' @@ -15,7 +12,6 @@ import { findConflictingEntries } from '@dotcom-tool-kit/types/lib/conflict' import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' -import { readState, configPaths, writeState } from '@dotcom-tool-kit/state' import { Hook, HookClass, invalid, Plugin, reduceValidated, valid, Validated } from '@dotcom-tool-kit/types' import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' @@ -32,6 +28,7 @@ import { formatInvalidOptions } from './messages' import { reducePluginHookInstallations } from './plugin/reduce-installations' +import { hasConfigChanged, updateHashes } from './config/hash' export interface PluginOptions { options: Record @@ -121,42 +118,6 @@ export const loadHookInstallations = async ( }) } -export async function fileHash(path: string): Promise { - const hashFunc = createHash('sha512') - try { - hashFunc.update(await readFile(path)) - return hashFunc.digest('base64') - } catch (error) { - if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') { - return 'n/a' - } else { - throw error - } - } -} - -export async function updateHashes(): Promise { - const hashes = Object.fromEntries( - await Promise.all(configPaths.map(async (path) => [path, await fileHash(path)])) - ) - writeState('install', hashes) -} - -async function hasConfigChanged(logger: Logger): Promise { - const hashes = readState('install') - if (!hashes) { - return true - } - for (const [path, prevHash] of Object.entries(hashes)) { - const newHash = await fileHash(path) - if (newHash !== prevHash) { - logger.debug(`hash for path ${path} has changed, running hook checks`) - return true - } - } - return false -} - export async function checkInstall(logger: Logger, config: ValidConfig): Promise { if (!(await hasConfigChanged(logger))) { return diff --git a/core/cli/src/config/hash.ts b/core/cli/src/config/hash.ts new file mode 100644 index 000000000..9bbe21619 --- /dev/null +++ b/core/cli/src/config/hash.ts @@ -0,0 +1,40 @@ +import { configPaths, readState, writeState } from '@dotcom-tool-kit/state' +import { createHash } from 'node:crypto' +import { readFile } from 'node:fs/promises' +import { Logger } from 'winston' + +export async function fileHash(path: string): Promise { + const hashFunc = createHash('sha512') + try { + hashFunc.update(await readFile(path)) + return hashFunc.digest('base64') + } catch (error) { + if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') { + return 'n/a' + } else { + throw error + } + } +} + +export async function updateHashes(): Promise { + const hashes = Object.fromEntries( + await Promise.all(configPaths.map(async (path) => [path, await fileHash(path)])) + ) + writeState('install', hashes) +} + +export async function hasConfigChanged(logger: Logger): Promise { + const hashes = readState('install') + if (!hashes) { + return true + } + for (const [path, prevHash] of Object.entries(hashes)) { + const newHash = await fileHash(path) + if (newHash !== prevHash) { + logger.debug(`hash for path ${path} has changed, running hook checks`) + return true + } + } + return false +} diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index ee10224b9..b7c4e256b 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -2,7 +2,8 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' -import { loadConfig, loadHookInstallations, updateHashes, ValidConfig } from './config' +import { loadConfig, loadHookInstallations, ValidConfig } from './config' +import { updateHashes } from './config/hash' // implementation of the Array.every method that supports asynchronous predicates async function asyncEvery(arr: T[], pred: (x: T) => Promise): Promise { From b2a70330c731644cf62ab0bf1077aec92b4a2bcd Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 11:12:47 +0000 Subject: [PATCH 062/321] refactor: move hook loading and checkInstall to install.ts --- core/cli/src/config.ts | 83 ++------------------------------------- core/cli/src/index.ts | 3 +- core/cli/src/install.ts | 86 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 84 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 2381fcafe..a3fa2242c 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -1,9 +1,8 @@ import path from 'path' import type { Logger } from 'winston' -import { z } from 'zod' import type { CommandTask } from './command' -import { importEntryPoint, loadPlugin, resolvePlugin } from './plugin' +import { loadPlugin, resolvePlugin } from './plugin' import { Conflict, findConflicts, @@ -11,10 +10,9 @@ import { isConflict, findConflictingEntries } from '@dotcom-tool-kit/types/lib/conflict' -import { ToolKitConflictError, ToolKitError } from '@dotcom-tool-kit/error' -import { Hook, HookClass, invalid, Plugin, reduceValidated, valid, Validated } from '@dotcom-tool-kit/types' +import { ToolKitConflictError } from '@dotcom-tool-kit/error' +import { Plugin, reduceValidated, Validated } from '@dotcom-tool-kit/types' import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' -import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' import { InvalidOption, formatTaskConflicts, @@ -23,12 +21,9 @@ import { formatCommandTaskConflicts, formatHookConflicts, formatOptionConflicts, - formatUninstalledHooks, formatMissingTasks, formatInvalidOptions } from './messages' -import { reducePluginHookInstallations } from './plugin/reduce-installations' -import { hasConfigChanged, updateHashes } from './config/hash' export interface PluginOptions { options: Record @@ -72,72 +67,6 @@ export type ValidConfig = Omit>> => { - const hookResultEntries = reduceValidated( - await Promise.all( - Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { - const hookResult = await importEntryPoint(Hook, entryPoint) - return hookResult.map((hookClass) => [hookName, hookClass as HookClass] as const) - }) - ) - ) - - return hookResultEntries.map((hookEntries) => Object.fromEntries(hookEntries)) -} - -export const loadHookInstallations = async ( - logger: Logger, - config: ValidConfig -): Promise[]>> => { - const hookClassResults = await loadHookEntrypoints(logger, config) - const installationResults = await hookClassResults - .map((hookClasses) => - reducePluginHookInstallations(logger, config, hookClasses, config.plugins['app root']) - ) - .awaitValue() - - const installationsWithoutConflicts = installationResults.flatMap((installations) => { - const conflicts = findConflicts(installations) - - if (conflicts.length) { - return invalid<[]>([]) - } - - return valid(withoutConflicts(installations)) - }) - - return installationsWithoutConflicts.map((installations) => { - return installations.map(({ hookConstructor, forHook, options }) => { - const schema = HookSchemas[forHook as keyof HookSchemaOptions] - const parsedOptions = schema ? schema.parse(options) : {} - return new hookConstructor(logger, forHook, parsedOptions) - }) - }) -} - -export async function checkInstall(logger: Logger, config: ValidConfig): Promise { - if (!(await hasConfigChanged(logger))) { - return - } - - const hooks = (await loadHookInstallations(logger, config)).unwrap('hooks are invalid') - - const uninstalledHooks = await asyncFilter(hooks, async (hook) => { - return !(await hook.isInstalled()) - }) - - if (uninstalledHooks.length > 0) { - const error = new ToolKitError('There are problems with your Tool Kit installation.') - error.details = formatUninstalledHooks(uninstalledHooks) - throw error - } - - await updateHashes() -} - export const createConfig = (): RawConfig => ({ root: coreRoot, plugins: {}, @@ -148,12 +77,6 @@ export const createConfig = (): RawConfig => ({ hooks: {} }) -async function asyncFilter(items: T[], predicate: (item: T) => Promise): Promise { - const results = await Promise.all(items.map(async (item) => ({ item, keep: await predicate(item) }))) - - return results.filter(({ keep }) => keep).map(({ item }) => item) -} - export function validateConfig(config: ValidPluginsConfig, logger: Logger): ValidConfig { const validConfig = config as ValidConfig diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 84b6e6be8..9b0753803 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -1,5 +1,5 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -import { ValidConfig, checkInstall, loadConfig } from './config' +import { ValidConfig, loadConfig } from './config' import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' @@ -7,6 +7,7 @@ import util from 'util' import { formatPluginTree } from './messages' import { Task, TaskConstructor, Validated, reduceValidated } from '@dotcom-tool-kit/types' import { importEntryPoint } from './plugin' +import { checkInstall } from './install' type ErrorSummary = { hook: string diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index b7c4e256b..2e8592cc8 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -1,11 +1,18 @@ +import { z } from 'zod' import { ToolKitError } from '@dotcom-tool-kit/error' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' -import { loadConfig, loadHookInstallations, ValidConfig } from './config' -import { updateHashes } from './config/hash' +import { loadConfig, ValidConfig } from './config' +import { hasConfigChanged, updateHashes } from './config/hash' +import { Hook, HookClass, Validated, invalid, reduceValidated, valid } from '@dotcom-tool-kit/types' +import { importEntryPoint } from './plugin' +import { reducePluginHookInstallations } from './plugin/reduce-installations' +import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/types/src/conflict' +import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' +import { formatUninstalledHooks } from './messages' -// implementation of the Array.every method that supports asynchronous predicates +// implementation of the Array#every method that supports asynchronous predicates async function asyncEvery(arr: T[], pred: (x: T) => Promise): Promise { for (const val of arr) { if (!(await pred(val))) { @@ -15,6 +22,79 @@ async function asyncEvery(arr: T[], pred: (x: T) => Promise): Promis return true } +// implementation of the Array#filter method that supports asynchronous predicates +async function asyncFilter(items: T[], predicate: (item: T) => Promise): Promise { + const results = await Promise.all(items.map(async (item) => ({ item, keep: await predicate(item) }))) + + return results.filter(({ keep }) => keep).map(({ item }) => item) +} + +const loadHookEntrypoints = async ( + logger: Logger, + config: ValidConfig +): Promise>> => { + const hookResultEntries = reduceValidated( + await Promise.all( + Object.entries(config.hooks).map(async ([hookName, entryPoint]) => { + const hookResult = await importEntryPoint(Hook, entryPoint) + return hookResult.map((hookClass) => [hookName, hookClass as HookClass] as const) + }) + ) + ) + + return hookResultEntries.map((hookEntries) => Object.fromEntries(hookEntries)) +} + +export const loadHookInstallations = async ( + logger: Logger, + config: ValidConfig +): Promise[]>> => { + const hookClassResults = await loadHookEntrypoints(logger, config) + const installationResults = await hookClassResults + .map((hookClasses) => + reducePluginHookInstallations(logger, config, hookClasses, config.plugins['app root']) + ) + .awaitValue() + + const installationsWithoutConflicts = installationResults.flatMap((installations) => { + const conflicts = findConflicts(installations) + + if (conflicts.length) { + return invalid<[]>([]) + } + + return valid(withoutConflicts(installations)) + }) + + return installationsWithoutConflicts.map((installations) => { + return installations.map(({ hookConstructor, forHook, options }) => { + const schema = HookSchemas[forHook as keyof HookSchemaOptions] + const parsedOptions = schema ? schema.parse(options) : {} + return new hookConstructor(logger, forHook, parsedOptions) + }) + }) +} + +export async function checkInstall(logger: Logger, config: ValidConfig): Promise { + if (!(await hasConfigChanged(logger))) { + return + } + + const hooks = (await loadHookInstallations(logger, config)).unwrap('hooks are invalid') + + const uninstalledHooks = await asyncFilter(hooks, async (hook) => { + return !(await hook.isInstalled()) + }) + + if (uninstalledHooks.length > 0) { + const error = new ToolKitError('There are problems with your Tool Kit installation.') + error.details = formatUninstalledHooks(uninstalledHooks) + throw error + } + + await updateHashes() +} + export default async function installHooks(logger: Logger): Promise { const config = await loadConfig(logger) From 11f6bb6c01e2411866da7f86c7f1e65ae24d698c Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 11:21:33 +0000 Subject: [PATCH 063/321] refactor: move core interfaces to types package --- core/cli/src/command.ts | 7 --- core/cli/src/config.ts | 50 +++------------------ core/cli/src/index.ts | 4 +- core/cli/src/install.ts | 12 ++++- core/cli/src/messages.ts | 4 +- core/cli/src/plugin.ts | 15 +++++-- core/cli/src/plugin/reduce-installations.ts | 3 +- core/create/src/prompts/conflicts.ts | 3 +- core/create/src/prompts/options.ts | 3 +- lib/types/src/index.ts | 50 +++++++++++++++++++++ 10 files changed, 85 insertions(+), 66 deletions(-) delete mode 100644 core/cli/src/command.ts diff --git a/core/cli/src/command.ts b/core/cli/src/command.ts deleted file mode 100644 index ca27c6429..000000000 --- a/core/cli/src/command.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Plugin } from '@dotcom-tool-kit/types' - -export interface CommandTask { - id: string - plugin: Plugin - tasks: string[] -} diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index a3fa2242c..615ae7815 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -1,17 +1,21 @@ import path from 'path' import type { Logger } from 'winston' -import type { CommandTask } from './command' import { loadPlugin, resolvePlugin } from './plugin' import { - Conflict, findConflicts, withoutConflicts, isConflict, findConflictingEntries } from '@dotcom-tool-kit/types/lib/conflict' import { ToolKitConflictError } from '@dotcom-tool-kit/error' -import { Plugin, reduceValidated, Validated } from '@dotcom-tool-kit/types' +import { + RawConfig, + reduceValidated, + Validated, + ValidConfig, + ValidPluginsConfig +} from '@dotcom-tool-kit/types' import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' import { InvalidOption, @@ -25,46 +29,6 @@ import { formatInvalidOptions } from './messages' -export interface PluginOptions { - options: Record - plugin: Plugin - forPlugin: Plugin -} - -export interface EntryPoint { - plugin: Plugin - modulePath: string -} - -export interface RawConfig { - root: string - plugins: { [id: string]: Validated } - resolvedPlugins: Set - tasks: { [id: string]: EntryPoint | Conflict } - commandTasks: { [id: string]: CommandTask | Conflict } - options: { [id: string]: PluginOptions | Conflict | undefined } - hooks: { [id: string]: EntryPoint | Conflict } -} - -export type ValidPluginsConfig = Omit & { - plugins: { [id: string]: Plugin } -} - -export type ValidPluginOptions = Omit & { - options: SchemaOptions[Id] -} - -export type ValidOptions = { - [Id in keyof SchemaOptions]: ValidPluginOptions -} - -export type ValidConfig = Omit & { - tasks: { [id: string]: EntryPoint } - commandTasks: { [id: string]: CommandTask } - options: ValidOptions - hooks: { [id: string]: EntryPoint } -} - const coreRoot = path.resolve(__dirname, '../') export const createConfig = (): RawConfig => ({ diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 9b0753803..18d8961f4 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -1,11 +1,11 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -import { ValidConfig, loadConfig } from './config' +import { loadConfig } from './config' import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' import util from 'util' import { formatPluginTree } from './messages' -import { Task, TaskConstructor, Validated, reduceValidated } from '@dotcom-tool-kit/types' +import { Task, TaskConstructor, ValidConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' import { importEntryPoint } from './plugin' import { checkInstall } from './install' diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 2e8592cc8..a54c3619e 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -3,9 +3,17 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' -import { loadConfig, ValidConfig } from './config' +import { loadConfig } from './config' import { hasConfigChanged, updateHashes } from './config/hash' -import { Hook, HookClass, Validated, invalid, reduceValidated, valid } from '@dotcom-tool-kit/types' +import { + Hook, + HookClass, + ValidConfig, + Validated, + invalid, + reduceValidated, + valid +} from '@dotcom-tool-kit/types' import { importEntryPoint } from './plugin' import { reducePluginHookInstallations } from './plugin/reduce-installations' import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/types/src/conflict' diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index d6f088012..2cad1c943 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -1,10 +1,8 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' -import type { Hook, Plugin } from '@dotcom-tool-kit/types' +import type { CommandTask, EntryPoint, Hook, Plugin, PluginOptions } from '@dotcom-tool-kit/types' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' -import type { EntryPoint, PluginOptions } from './config' import type { Conflict } from '@dotcom-tool-kit/types/lib/conflict' -import type { CommandTask } from './command' const formatTaskConflict = ([key, conflict]: [string, Conflict]): string => `- ${s.task(key ?? 'unknown task')} ${s.dim('from plugins')} ${conflict.conflicting diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 0d46bcbf1..3422e28c8 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,10 +1,19 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import { invalid, Plugin, reduceValidated, valid, Validated } from '@dotcom-tool-kit/types' +import { + CommandTask, + EntryPoint, + invalid, + Plugin, + PluginOptions, + RawConfig, + reduceValidated, + valid, + Validated, + ValidPluginsConfig +} from '@dotcom-tool-kit/types' import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' -import { EntryPoint, PluginOptions, RawConfig, ValidPluginsConfig } from './config' import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' -import type { CommandTask } from './command' import { loadToolKitRC } from './rc-file' import { isPlainObject } from 'lodash' import { Base } from '@dotcom-tool-kit/types/src/base' diff --git a/core/cli/src/plugin/reduce-installations.ts b/core/cli/src/plugin/reduce-installations.ts index f38412a4a..7042fd769 100644 --- a/core/cli/src/plugin/reduce-installations.ts +++ b/core/cli/src/plugin/reduce-installations.ts @@ -1,6 +1,5 @@ import { Logger } from 'winston' -import { ValidConfig } from '../config' -import { HookClass, HookInstallation, Plugin } from '@dotcom-tool-kit/types' +import { HookClass, HookInstallation, Plugin, ValidConfig } from '@dotcom-tool-kit/types' import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' import { groupBy } from 'lodash' import { HookSchemas, Options as HookOptions } from '@dotcom-tool-kit/types/src/hooks' diff --git a/core/create/src/prompts/conflicts.ts b/core/create/src/prompts/conflicts.ts index 30c6852d3..c4137f310 100644 --- a/core/create/src/prompts/conflicts.ts +++ b/core/create/src/prompts/conflicts.ts @@ -1,7 +1,6 @@ import * as ToolkitErrorModule from '@dotcom-tool-kit/error' import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' -import type { RCFile } from '@dotcom-tool-kit/types' -import type { ValidConfig } from 'dotcom-tool-kit/lib/config' +import type { RCFile, ValidConfig } from '@dotcom-tool-kit/types' import type installHooksType from 'dotcom-tool-kit/lib/install' import { promises as fs } from 'fs' import importCwd from 'import-cwd' diff --git a/core/create/src/prompts/options.ts b/core/create/src/prompts/options.ts index ba1f2bdb2..be4c83b0c 100644 --- a/core/create/src/prompts/options.ts +++ b/core/create/src/prompts/options.ts @@ -1,7 +1,6 @@ import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' -import type { RCFile } from '@dotcom-tool-kit/types' +import type { RCFile, RawConfig } from '@dotcom-tool-kit/types' import type { PromptGenerators } from '@dotcom-tool-kit/types/src/plugins' -import type { RawConfig } from 'dotcom-tool-kit/lib/config' import { promises as fs } from 'fs' import YAML from 'yaml' import type Logger from 'komatsu' diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index a77697da2..9c1699881 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -1,3 +1,7 @@ +import type { Conflict } from './conflict' +import type { Validated } from './validated' +import type { Options as SchemaOptions } from './plugins' + export * from './validated' export * from './base' export * from './task' @@ -19,3 +23,49 @@ export interface Plugin { parent?: Plugin children?: Plugin[] } + +export interface CommandTask { + id: string + plugin: Plugin + tasks: string[] +} + +export interface PluginOptions { + options: Record + plugin: Plugin + forPlugin: Plugin +} + +export interface EntryPoint { + plugin: Plugin + modulePath: string +} + +export interface RawConfig { + root: string + plugins: { [id: string]: Validated } + resolvedPlugins: Set + tasks: { [id: string]: EntryPoint | Conflict } + commandTasks: { [id: string]: CommandTask | Conflict } + options: { [id: string]: PluginOptions | Conflict | undefined } + hooks: { [id: string]: EntryPoint | Conflict } +} + +export type ValidPluginsConfig = Omit & { + plugins: { [id: string]: Plugin } +} + +export type ValidPluginOptions = Omit & { + options: SchemaOptions[Id] +} + +export type ValidOptions = { + [Id in keyof SchemaOptions]: ValidPluginOptions +} + +export type ValidConfig = Omit & { + tasks: { [id: string]: EntryPoint } + commandTasks: { [id: string]: CommandTask } + options: ValidOptions + hooks: { [id: string]: EntryPoint } +} From 17c44697ae19ec055de755e204a36ddc76c3c3bc Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 11:31:31 +0000 Subject: [PATCH 064/321] refactor: move importEntryPoint to its own module --- core/cli/src/index.ts | 2 +- core/cli/src/install.ts | 2 +- core/cli/src/messages.ts | 2 + core/cli/src/plugin.ts | 58 +---------------------------- core/cli/src/plugin/entry-point.ts | 59 ++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 59 deletions(-) create mode 100644 core/cli/src/plugin/entry-point.ts diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 18d8961f4..2cefa6f73 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -6,8 +6,8 @@ import type { Logger } from 'winston' import util from 'util' import { formatPluginTree } from './messages' import { Task, TaskConstructor, ValidConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' -import { importEntryPoint } from './plugin' import { checkInstall } from './install' +import { importEntryPoint } from './plugin/entry-point' type ErrorSummary = { hook: string diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index a54c3619e..ea551ea26 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -14,11 +14,11 @@ import { reduceValidated, valid } from '@dotcom-tool-kit/types' -import { importEntryPoint } from './plugin' import { reducePluginHookInstallations } from './plugin/reduce-installations' import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/types/src/conflict' import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' import { formatUninstalledHooks } from './messages' +import { importEntryPoint } from './plugin/entry-point' // implementation of the Array#every method that supports asynchronous predicates async function asyncEvery(arr: T[], pred: (x: T) => Promise): Promise { diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 2cad1c943..6feab673c 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -159,3 +159,5 @@ export function formatPluginTree(plugin: Plugin): string[] { ) ] } + +export const indentReasons = (reasons: string): string => reasons.replace(/\n/g, '\n ') diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 3422e28c8..f670d7e6e 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -15,8 +15,7 @@ import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' import { loadToolKitRC } from './rc-file' -import { isPlainObject } from 'lodash' -import { Base } from '@dotcom-tool-kit/types/src/base' +import { indentReasons } from './messages' function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { if (!possibleDescendent.parent) { @@ -28,61 +27,6 @@ function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boo } } -const isPlainObjectGuard = (value: unknown): value is Record => isPlainObject(value) - -// the subclasses of Base have different constructor signatures so we need to omit -// the constructor from the type bound here so you can actually pass in a subclass -export async function importEntryPoint>( - type: T, - entryPoint: EntryPoint -): Promise> { - const resolvedPath = resolvePkg(entryPoint.modulePath, { cwd: entryPoint.plugin.root }) - - if (!resolvedPath) { - return invalid([ - `could not find entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( - entryPoint.plugin.id - )}` - ]) - } - - let pluginModule: unknown - try { - pluginModule = await import(resolvedPath) - } catch (e) { - const err = e as Error - return invalid([ - `an error was thrown when loading entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( - entryPoint.plugin.id - )}:\n ${s.code(indentReasons(err.toString()))}` - ]) - } - - if ( - isPlainObjectGuard(pluginModule) && - 'default' in pluginModule && - typeof pluginModule.default === 'function' - ) { - const name = pluginModule.default.name - - return type - .isCompatible(pluginModule.default) - .mapError((reasons) => [ - `the ${type.name.toLowerCase()} ${s.hook(name)} is not a compatible instance of ${s.code( - type.name - )}:\n - ${reasons.join('\n - ')}` - ]) - } else { - return invalid([ - `entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( - entryPoint.plugin.id - )} does not have a ${s.code('default')} export` - ]) - } -} - -const indentReasons = (reasons: string): string => reasons.replace(/\n/g, '\n ') - export async function loadPlugin( id: string, config: RawConfig, diff --git a/core/cli/src/plugin/entry-point.ts b/core/cli/src/plugin/entry-point.ts new file mode 100644 index 000000000..768d23df0 --- /dev/null +++ b/core/cli/src/plugin/entry-point.ts @@ -0,0 +1,59 @@ +import { styles as s } from '@dotcom-tool-kit/logger' + +import { Base, EntryPoint, Validated, invalid } from '@dotcom-tool-kit/types' +import resolvePkg from 'resolve-pkg' +import { isPlainObject } from 'lodash' +import { indentReasons } from '../messages' + +const isPlainObjectGuard = (value: unknown): value is Record => isPlainObject(value) + +// the subclasses of Base have different constructor signatures so we need to omit +// the constructor from the type bound here so you can actually pass in a subclass +export async function importEntryPoint>( + type: T, + entryPoint: EntryPoint +): Promise> { + const resolvedPath = resolvePkg(entryPoint.modulePath, { cwd: entryPoint.plugin.root }) + + if (!resolvedPath) { + return invalid([ + `could not find entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( + entryPoint.plugin.id + )}` + ]) + } + + let pluginModule: unknown + try { + pluginModule = await import(resolvedPath) + } catch (e) { + const err = e as Error + return invalid([ + `an error was thrown when loading entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( + entryPoint.plugin.id + )}:\n ${s.code(indentReasons(err.toString()))}` + ]) + } + + if ( + isPlainObjectGuard(pluginModule) && + 'default' in pluginModule && + typeof pluginModule.default === 'function' + ) { + const name = pluginModule.default.name + + return type + .isCompatible(pluginModule.default) + .mapError((reasons) => [ + `the ${type.name.toLowerCase()} ${s.hook(name)} is not a compatible instance of ${s.code( + type.name + )}:\n - ${reasons.join('\n - ')}` + ]) + } else { + return invalid([ + `entrypoint ${s.filepath(entryPoint.modulePath)} in plugin ${s.plugin( + entryPoint.plugin.id + )} does not have a ${s.code('default')} export` + ]) + } +} From 9626cc9c2e56ceff1ab38e57c3b06fe7ceb2402a Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 11:47:07 +0000 Subject: [PATCH 065/321] refactor: move runTasks and shouldDisableNativeFetch to their own files --- core/cli/src/fetch.ts | 17 ++++++ core/cli/src/index.ts | 132 +----------------------------------------- core/cli/src/tasks.ts | 118 +++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 130 deletions(-) create mode 100644 core/cli/src/fetch.ts create mode 100644 core/cli/src/tasks.ts diff --git a/core/cli/src/fetch.ts b/core/cli/src/fetch.ts new file mode 100644 index 000000000..7de0cedf6 --- /dev/null +++ b/core/cli/src/fetch.ts @@ -0,0 +1,17 @@ +import { getOptions } from '@dotcom-tool-kit/options' + +// function that plugins can check if they need to implement their own logic to +// disable Node 18's native fetch +export const shouldDisableNativeFetch = (): boolean => { + // disable Node 18's native fetch if the Node runtime supports it (older + // runtimes don't support the flag, implying they also don't use native + // fetch) and the user hasn't opted out of the behaviour + return ( + /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- + * the root plugin has default options and it always exists so is always + * defined + **/ + !getOptions('app root')!.allowNativeFetch && + process.allowedNodeEnvironmentFlags.has('--no-experimental-fetch') + ) +} diff --git a/core/cli/src/index.ts b/core/cli/src/index.ts index 2cefa6f73..617101838 100644 --- a/core/cli/src/index.ts +++ b/core/cli/src/index.ts @@ -1,138 +1,10 @@ -import { ToolKitError } from '@dotcom-tool-kit/error' import { loadConfig } from './config' -import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' -import { styles } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' import util from 'util' import { formatPluginTree } from './messages' -import { Task, TaskConstructor, ValidConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' -import { checkInstall } from './install' -import { importEntryPoint } from './plugin/entry-point' -type ErrorSummary = { - hook: string - task: string - error: Error -} - -// function that plugins can check if they need to implement their own logic to -// disable Node 18's native fetch -export const shouldDisableNativeFetch = (): boolean => { - // disable Node 18's native fetch if the Node runtime supports it (older - // runtimes don't support the flag, implying they also don't use native - // fetch) and the user hasn't opted out of the behaviour - return ( - /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- - * the root plugin has default options and it always exists so is always - * defined - **/ - !getOptions('app root')!.allowNativeFetch && - process.allowedNodeEnvironmentFlags.has('--no-experimental-fetch') - ) -} - -const loadTasks = async ( - logger: Logger, - taskNames: string[], - config: ValidConfig -): Promise>> => { - const taskResults = await Promise.all( - taskNames.map(async (taskName) => { - const entryPoint = config.tasks[taskName] - const taskResult = await importEntryPoint(Task, entryPoint) - - return taskResult.map((Task) => [ - taskName, - new ((Task as unknown) as TaskConstructor)( - logger, - taskName, - getOptions(entryPoint.plugin.id as OptionKey) ?? {} - ) - ]) - }) - ) - - return reduceValidated(taskResults).map(Object.fromEntries) -} - -export async function runTasks(logger: Logger, hooks: string[], files?: string[]): Promise { - const config = await loadConfig(logger) - - const availableHooks = Object.keys(config.hooks) - .sort() - .map((id) => `- ${id}`) - .join('\n') - - const missingHooks = hooks.filter((id) => !config.hooks[id]) - - if (missingHooks.length > 0) { - const error = new ToolKitError(`hooks ${missingHooks} do not exist`) - error.details = `maybe you need to install a plugin to handle these hooks, or configure them in your Tool Kit configuration. - -hooks that are available are: -${availableHooks}` - throw error - } - - for (const pluginOptions of Object.values(config.options)) { - if (pluginOptions.forPlugin) { - setOptions(pluginOptions.forPlugin.id as OptionKey, pluginOptions.options) - } - } - - await checkInstall(logger, config) - - if (shouldDisableNativeFetch()) { - process.execArgv.push('--no-experimental-fetch') - } - - const taskNames = hooks.flatMap((hook) => config.commandTasks[hook]?.tasks ?? []) - const tasks = (await loadTasks(logger, taskNames, config)).unwrap('tasks are invalid') - - for (const hook of hooks) { - const errors: ErrorSummary[] = [] - - if (!config.commandTasks[hook]) { - logger.warn(`no task configured for ${hook}: skipping assignment...`) - continue - } - - for (const id of config.commandTasks[hook].tasks) { - try { - logger.info(styles.taskHeader(`running ${styles.task(id)} task`)) - await tasks[id].run(files) - } catch (error) { - // allow subsequent hook tasks to run on error - errors.push({ - hook, - task: id, - error: error as Error - }) - } - } - - if (errors.length > 0) { - const error = new ToolKitError(`error running tasks for ${styles.hook(hook)}`) - error.details = errors - .map( - ({ task, error }) => - `${styles.heading(`${styles.task(task)}:`)} - -${error.message}${ - error instanceof ToolKitError - ? ` - -${error.details}` - : '' - }` - ) - .join(`${styles.dim(styles.ruler())}\n`) - - error.exitCode = errors.length + 1 - throw error - } - } -} +export { runTasks } from './tasks' +export { shouldDisableNativeFetch } from './fetch' export async function listPlugins(logger: Logger): Promise { const config = await loadConfig(logger, { validate: false }) diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts new file mode 100644 index 000000000..75a762fa9 --- /dev/null +++ b/core/cli/src/tasks.ts @@ -0,0 +1,118 @@ +import { Task, TaskConstructor, ValidConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' +import type { Logger } from 'winston' +import { importEntryPoint } from './plugin/entry-point' +import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' +import { loadConfig } from './config' +import { ToolKitError } from '@dotcom-tool-kit/error' +import { checkInstall } from './install' +import { styles } from '@dotcom-tool-kit/logger' +import { shouldDisableNativeFetch } from './fetch' + +type ErrorSummary = { + hook: string + task: string + error: Error +} + +const loadTasks = async ( + logger: Logger, + taskNames: string[], + config: ValidConfig +): Promise>> => { + const taskResults = await Promise.all( + taskNames.map(async (taskName) => { + const entryPoint = config.tasks[taskName] + const taskResult = await importEntryPoint(Task, entryPoint) + + return taskResult.map((Task) => [ + taskName, + new ((Task as unknown) as TaskConstructor)( + logger, + taskName, + getOptions(entryPoint.plugin.id as OptionKey) ?? {} + ) + ]) + }) + ) + + return reduceValidated(taskResults).map(Object.fromEntries) +} + +export async function runTasks(logger: Logger, hooks: string[], files?: string[]): Promise { + const config = await loadConfig(logger) + + const availableHooks = Object.keys(config.hooks) + .sort() + .map((id) => `- ${id}`) + .join('\n') + + const missingHooks = hooks.filter((id) => !config.hooks[id]) + + if (missingHooks.length > 0) { + const error = new ToolKitError(`hooks ${missingHooks} do not exist`) + error.details = `maybe you need to install a plugin to handle these hooks, or configure them in your Tool Kit configuration. + +hooks that are available are: +${availableHooks}` + throw error + } + + for (const pluginOptions of Object.values(config.options)) { + if (pluginOptions.forPlugin) { + setOptions(pluginOptions.forPlugin.id as OptionKey, pluginOptions.options) + } + } + + await checkInstall(logger, config) + + if (shouldDisableNativeFetch()) { + process.execArgv.push('--no-experimental-fetch') + } + + const taskNames = hooks.flatMap((hook) => config.commandTasks[hook]?.tasks ?? []) + const tasks = (await loadTasks(logger, taskNames, config)).unwrap('tasks are invalid') + + for (const hook of hooks) { + const errors: ErrorSummary[] = [] + + if (!config.commandTasks[hook]) { + logger.warn(`no task configured for ${hook}: skipping assignment...`) + continue + } + + for (const id of config.commandTasks[hook].tasks) { + try { + logger.info(styles.taskHeader(`running ${styles.task(id)} task`)) + await tasks[id].run(files) + } catch (error) { + // allow subsequent hook tasks to run on error + errors.push({ + hook, + task: id, + error: error as Error + }) + } + } + + if (errors.length > 0) { + const error = new ToolKitError(`error running tasks for ${styles.hook(hook)}`) + error.details = errors + .map( + ({ task, error }) => + `${styles.heading(`${styles.task(task)}:`)} + +${error.message}${ + error instanceof ToolKitError + ? ` + +${error.details}` + : '' + }` + ) + .join(`${styles.dim(styles.ruler())}\n`) + + error.exitCode = errors.length + 1 + throw error + } + } +} From 99149635644afd34131287ccff5f27a2bd900831 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 11:57:40 +0000 Subject: [PATCH 066/321] refactor: move plugin option validation to own file --- core/cli/src/config.ts | 53 ++----------------------- core/cli/src/config/validate-plugins.ts | 8 ++++ core/cli/src/plugin/options.ts | 45 +++++++++++++++++++++ core/cli/test/index.test.ts | 5 ++- 4 files changed, 60 insertions(+), 51 deletions(-) create mode 100644 core/cli/src/config/validate-plugins.ts create mode 100644 core/cli/src/plugin/options.ts diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 615ae7815..b1138366e 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -9,16 +9,8 @@ import { findConflictingEntries } from '@dotcom-tool-kit/types/lib/conflict' import { ToolKitConflictError } from '@dotcom-tool-kit/error' +import { RawConfig, ValidConfig, ValidPluginsConfig } from '@dotcom-tool-kit/types' import { - RawConfig, - reduceValidated, - Validated, - ValidConfig, - ValidPluginsConfig -} from '@dotcom-tool-kit/types' -import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' -import { - InvalidOption, formatTaskConflicts, formatUndefinedCommandTasks, formatUnusedOptions, @@ -28,6 +20,8 @@ import { formatMissingTasks, formatInvalidOptions } from './messages' +import { validatePlugins } from './config/validate-plugins' +import { validatePluginOptions } from './plugin/options' const coreRoot = path.resolve(__dirname, '../') @@ -105,40 +99,8 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali error.details += formatUndefinedCommandTasks(undefinedCommandTasks, Array.from(definedHookIds)) } - const invalidOptions: InvalidOption[] = [] - for (const [id, plugin] of Object.entries(config.plugins)) { - const pluginId = id as keyof SchemaOptions - const pluginOptions = config.options[pluginId] - if (pluginOptions && isConflict(pluginOptions)) { - continue - } + const invalidOptions = validatePluginOptions(logger, config) - const pluginSchema = Schemas[pluginId] - if (!pluginSchema) { - logger.silly(`skipping validation of ${pluginId} plugin as no schema can be found`) - continue - } - const result = pluginSchema.safeParse(pluginOptions?.options ?? {}) - if (result.success) { - // Set up options entry for plugins that don't have options specified - // explicitly. They could still have default options that are set by zod. - if (!pluginOptions) { - // TypeScript struggles with this type as it sees one side as - // `Foo` and the other as `Foo | Foo | Foo` for - // some reason (something to do with the record indexing) and it can't - // unify them. But they are equivalent so let's force it with a cast. - config.options[pluginId] = { - options: result.data, - plugin: config.plugins['app root'], - forPlugin: plugin - } as any // eslint-disable-line @typescript-eslint/no-explicit-any - } else { - pluginOptions.options = result.data - } - } else { - invalidOptions.push([id, result.error]) - } - } if (invalidOptions.length > 0) { shouldThrow = true error.details += formatInvalidOptions(invalidOptions) @@ -174,13 +136,6 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali return validConfig } -export function validatePlugins(config: RawConfig): Validated { - const validatedPlugins = reduceValidated( - Object.entries(config.plugins).map(([id, plugin]) => plugin.map((p) => [id, p] as const)) - ) - return validatedPlugins.map((plugins) => ({ ...config, plugins: Object.fromEntries(plugins) })) -} - export function loadConfig(logger: Logger, options?: { validate?: true }): Promise export function loadConfig(logger: Logger, options?: { validate?: false }): Promise diff --git a/core/cli/src/config/validate-plugins.ts b/core/cli/src/config/validate-plugins.ts new file mode 100644 index 000000000..320ac1b18 --- /dev/null +++ b/core/cli/src/config/validate-plugins.ts @@ -0,0 +1,8 @@ +import { RawConfig, ValidPluginsConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' + +export function validatePlugins(config: RawConfig): Validated { + const validatedPlugins = reduceValidated( + Object.entries(config.plugins).map(([id, plugin]) => plugin.map((p) => [id, p] as const)) + ) + return validatedPlugins.map((plugins) => ({ ...config, plugins: Object.fromEntries(plugins) })) +} diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts new file mode 100644 index 000000000..02ee625dc --- /dev/null +++ b/core/cli/src/plugin/options.ts @@ -0,0 +1,45 @@ +import { ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { InvalidOption } from '../messages' +import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' +import { isConflict } from '@dotcom-tool-kit/types/src/conflict' +import type { Logger } from 'winston' + +export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig): InvalidOption[] => { + const invalidOptions: InvalidOption[] = [] + + for (const [id, plugin] of Object.entries(config.plugins)) { + const pluginId = id as keyof SchemaOptions + const pluginOptions = config.options[pluginId] + if (pluginOptions && isConflict(pluginOptions)) { + continue + } + + const pluginSchema = Schemas[pluginId] + if (!pluginSchema) { + logger.silly(`skipping validation of ${pluginId} plugin as no schema can be found`) + continue + } + const result = pluginSchema.safeParse(pluginOptions?.options ?? {}) + if (result.success) { + // Set up options entry for plugins that don't have options specified + // explicitly. They could still have default options that are set by zod. + if (!pluginOptions) { + // TypeScript struggles with this type as it sees one side as + // `Foo` and the other as `Foo | Foo | Foo` for + // some reason (something to do with the record indexing) and it can't + // unify them. But they are equivalent so let's force it with a cast. + config.options[pluginId] = { + options: result.data, + plugin: config.plugins['app root'], + forPlugin: plugin + } as any // eslint-disable-line @typescript-eslint/no-explicit-any + } else { + pluginOptions.options = result.data + } + } else { + invalidOptions.push([id, result.error]) + } + } + + return invalidOptions +} diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index 97ab6b9b0..d5b6c2186 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -1,10 +1,11 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -import { Plugin, Valid } from '@dotcom-tool-kit/types' +import { Plugin, Valid, ValidPluginsConfig } from '@dotcom-tool-kit/types' import { describe, expect, it, jest } from '@jest/globals' import * as path from 'path' import winston, { Logger } from 'winston' -import { createConfig, validateConfig, validatePlugins, ValidPluginsConfig } from '../src/config' +import { createConfig, validateConfig } from '../src/config' import { loadPlugin, resolvePlugin } from '../src/plugin' +import { validatePlugins } from '../src/config/validate-plugins' const logger = (winston as unknown) as Logger From a74ec969d493901ee6bcc2d005d4190f6ae48440 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 12:26:24 +0000 Subject: [PATCH 067/321] refactor: split the plugin merge functions into their own modules --- core/cli/src/plugin.ts | 139 ++------------------------ core/cli/src/plugin/is-descendent.ts | 11 ++ core/cli/src/plugin/merge-commands.ts | 44 ++++++++ core/cli/src/plugin/merge-hooks.ts | 27 +++++ core/cli/src/plugin/merge-options.ts | 47 +++++++++ core/cli/src/plugin/merge-tasks.ts | 26 +++++ 6 files changed, 163 insertions(+), 131 deletions(-) create mode 100644 core/cli/src/plugin/is-descendent.ts create mode 100644 core/cli/src/plugin/merge-commands.ts create mode 100644 core/cli/src/plugin/merge-hooks.ts create mode 100644 core/cli/src/plugin/merge-options.ts create mode 100644 core/cli/src/plugin/merge-tasks.ts diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index f670d7e6e..8e9d8a090 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -16,16 +16,10 @@ import type { Logger } from 'winston' import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' import { loadToolKitRC } from './rc-file' import { indentReasons } from './messages' - -function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { - if (!possibleDescendent.parent) { - return false - } else if (possibleDescendent.parent === possibleAncestor) { - return true - } else { - return isDescendent(possibleAncestor, possibleDescendent.parent) - } -} +import { mergePluginTasks } from './plugin/merge-tasks' +import { mergePluginHooks } from './plugin/merge-hooks' +import { mergePluginCommands } from './plugin/merge-commands' +import { mergePluginOptions } from './plugin/merge-options' export async function loadPlugin( id: string, @@ -89,127 +83,10 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger } } - if (plugin.rcFile) { - // add plugin tasks to our task registry, handling any conflicts - for (const [taskName, modulePath] of Object.entries(plugin.rcFile.tasks || {})) { - const existingTaskId = config.tasks[taskName] - const entryPoint: EntryPoint = { - plugin, - modulePath - } - - if (existingTaskId) { - const conflicting = isConflict(existingTaskId) ? existingTaskId.conflicting : [existingTaskId] - - config.tasks[taskName] = { - plugin, - conflicting: conflicting.concat(entryPoint) - } - } else { - config.tasks[taskName] = entryPoint - } - } - - // add hooks to the registry, handling any conflicts - // TODO refactor with command conflict handler - for (const [hookName, modulePath] of Object.entries(plugin.rcFile.installs || {})) { - const existingHookId = config.hooks[hookName] - const entryPoint: EntryPoint = { - plugin, - modulePath - } - - if (existingHookId) { - const conflicting = isConflict(existingHookId) ? existingHookId.conflicting : [existingHookId] - - config.hooks[hookName] = { - plugin, - conflicting: conflicting.concat(entryPoint) - } - } else { - config.hooks[hookName] = entryPoint - } - } - - // load plugin command tasks. do this after loading child plugins, so - // parent commands get assigned after child commands and can override them - for (const [id, configCommandTask] of Object.entries(plugin.rcFile.commands)) { - // handle conflicts between commands from different plugins - const existingCommandTask = config.commandTasks[id] - const newCommandTask: CommandTask = { - id, - plugin, - tasks: Array.isArray(configCommandTask) ? configCommandTask : [configCommandTask] - } - - if (existingCommandTask) { - const existingFromDescendent = isDescendent(plugin, existingCommandTask.plugin) - - // plugins can only override command tasks from their descendents, otherwise that's a conflict - // return a conflict either listing this command and the siblings, - // or merging in a previously-generated command - if (!existingFromDescendent) { - const conflicting = isConflict(existingCommandTask) - ? existingCommandTask.conflicting - : [existingCommandTask] - - const conflict: Conflict = { - plugin, - conflicting: conflicting.concat(newCommandTask) - } - - config.commandTasks[id] = conflict - } else { - // if we're here, any existing command is from a child plugin, - // so the parent always overrides it - config.commandTasks[id] = newCommandTask - } - } else { - // this command task might not have been set yet, in which case use the new one - config.commandTasks[id] = newCommandTask - } - } - - // merge options from this plugin's config with any options we've collected already - // TODO this is almost the exact same code as for command tasks, refactor - for (const [id, configOptions] of Object.entries(plugin.rcFile.options)) { - // users can specify root options with the dotcom-tool-kit key to mirror - // the name of the root npm package - const pluginId = id === 'dotcom-tool-kit' ? 'app root' : id - const existingOptions = config.options[pluginId] - - const pluginOptions: PluginOptions = { - options: configOptions, - plugin, - forPlugin: config.plugins[pluginId] - } - - if (existingOptions) { - const existingFromDescendent = isDescendent(plugin, existingOptions.plugin) - - // plugins can only override options from their descendents, otherwise it's a conflict - // return a conflict either listing these options and the sibling's, - // or merging in previously-generated options - if (!existingFromDescendent) { - const conflicting = isConflict(existingOptions) ? existingOptions.conflicting : [existingOptions] - - const conflict: Conflict = { - plugin, - conflicting: conflicting.concat(pluginOptions) - } - - config.options[pluginId] = conflict - } else { - // if we're here, any existing options are from a child plugin, - // so merge in overrides from the parent - config.options[pluginId] = { ...existingOptions, ...pluginOptions } - } - } else { - // this options key might not have been set yet, in which case use the new one - config.options[pluginId] = pluginOptions - } - } - } + mergePluginTasks(config, plugin) + mergePluginHooks(config, plugin) + mergePluginCommands(config, plugin) + mergePluginOptions(config, plugin) config.resolvedPlugins.add(plugin.id) } diff --git a/core/cli/src/plugin/is-descendent.ts b/core/cli/src/plugin/is-descendent.ts new file mode 100644 index 000000000..ac16ef99e --- /dev/null +++ b/core/cli/src/plugin/is-descendent.ts @@ -0,0 +1,11 @@ +import { Plugin } from '@dotcom-tool-kit/types' + +export function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { + if (!possibleDescendent.parent) { + return false + } else if (possibleDescendent.parent === possibleAncestor) { + return true + } else { + return isDescendent(possibleAncestor, possibleDescendent.parent) + } +} diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts new file mode 100644 index 000000000..8e2f94ee4 --- /dev/null +++ b/core/cli/src/plugin/merge-commands.ts @@ -0,0 +1,44 @@ +import { CommandTask, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { isDescendent } from './is-descendent' + +export const mergePluginCommands = (config: ValidPluginsConfig, plugin: Plugin) => { + if (plugin.rcFile) { + for (const [id, configCommandTask] of Object.entries(plugin.rcFile.commands)) { + // handle conflicts between commands from different plugins + const existingCommandTask = config.commandTasks[id] + const newCommandTask: CommandTask = { + id, + plugin, + tasks: Array.isArray(configCommandTask) ? configCommandTask : [configCommandTask] + } + + if (existingCommandTask) { + const existingFromDescendent = isDescendent(plugin, existingCommandTask.plugin) + + // plugins can only override command tasks from their descendents, otherwise that's a conflict + // return a conflict either listing this command and the siblings, + // or merging in a previously-generated command + if (!existingFromDescendent) { + const conflicting = isConflict(existingCommandTask) + ? existingCommandTask.conflicting + : [existingCommandTask] + + const conflict: Conflict = { + plugin, + conflicting: conflicting.concat(newCommandTask) + } + + config.commandTasks[id] = conflict + } else { + // if we're here, any existing command is from a child plugin, + // so the parent always overrides it + config.commandTasks[id] = newCommandTask + } + } else { + // this command task might not have been set yet, in which case use the new one + config.commandTasks[id] = newCommandTask + } + } + } +} diff --git a/core/cli/src/plugin/merge-hooks.ts b/core/cli/src/plugin/merge-hooks.ts new file mode 100644 index 000000000..91e7f2610 --- /dev/null +++ b/core/cli/src/plugin/merge-hooks.ts @@ -0,0 +1,27 @@ +import { EntryPoint, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { isConflict } from '@dotcom-tool-kit/types/src/conflict' + +export const mergePluginHooks = (config: ValidPluginsConfig, plugin: Plugin) => { + if (plugin.rcFile) { + // add hooks to the registry, handling any conflicts + // TODO refactor with command conflict handler + for (const [hookName, modulePath] of Object.entries(plugin.rcFile.installs || {})) { + const existingHookId = config.hooks[hookName] + const entryPoint: EntryPoint = { + plugin, + modulePath + } + + if (existingHookId) { + const conflicting = isConflict(existingHookId) ? existingHookId.conflicting : [existingHookId] + + config.hooks[hookName] = { + plugin, + conflicting: conflicting.concat(entryPoint) + } + } else { + config.hooks[hookName] = entryPoint + } + } + } +} diff --git a/core/cli/src/plugin/merge-options.ts b/core/cli/src/plugin/merge-options.ts new file mode 100644 index 000000000..9b3095f5a --- /dev/null +++ b/core/cli/src/plugin/merge-options.ts @@ -0,0 +1,47 @@ +import { Plugin, PluginOptions, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { isDescendent } from './is-descendent' +import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' + +// merge options from this plugin's config with any options we've collected already +// TODO this is almost the exact same code as for command tasks, refactor +export const mergePluginOptions = (config: ValidPluginsConfig, plugin: Plugin) => { + if (plugin.rcFile) { + for (const [id, configOptions] of Object.entries(plugin.rcFile.options)) { + // users can specify root options with the dotcom-tool-kit key to mirror + // the name of the root npm package + const pluginId = id === 'dotcom-tool-kit' ? 'app root' : id + const existingOptions = config.options[pluginId] + + const pluginOptions: PluginOptions = { + options: configOptions, + plugin, + forPlugin: config.plugins[pluginId] + } + + if (existingOptions) { + const existingFromDescendent = isDescendent(plugin, existingOptions.plugin) + + // plugins can only override options from their descendents, otherwise it's a conflict + // return a conflict either listing these options and the sibling's, + // or merging in previously-generated options + if (!existingFromDescendent) { + const conflicting = isConflict(existingOptions) ? existingOptions.conflicting : [existingOptions] + + const conflict: Conflict = { + plugin, + conflicting: conflicting.concat(pluginOptions) + } + + config.options[pluginId] = conflict + } else { + // if we're here, any existing options are from a child plugin, + // so merge in overrides from the parent + config.options[pluginId] = { ...existingOptions, ...pluginOptions } + } + } else { + // this options key might not have been set yet, in which case use the new one + config.options[pluginId] = pluginOptions + } + } + } +} diff --git a/core/cli/src/plugin/merge-tasks.ts b/core/cli/src/plugin/merge-tasks.ts new file mode 100644 index 000000000..5977d11e1 --- /dev/null +++ b/core/cli/src/plugin/merge-tasks.ts @@ -0,0 +1,26 @@ +import { EntryPoint, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { isConflict } from '@dotcom-tool-kit/types/src/conflict' + +// add plugin tasks to our task registry, handling any conflicts +export const mergePluginTasks = (config: ValidPluginsConfig, plugin: Plugin) => { + if (plugin.rcFile) { + for (const [taskName, modulePath] of Object.entries(plugin.rcFile.tasks || {})) { + const existingTaskId = config.tasks[taskName] + const entryPoint: EntryPoint = { + plugin, + modulePath + } + + if (existingTaskId) { + const conflicting = isConflict(existingTaskId) ? existingTaskId.conflicting : [existingTaskId] + + config.tasks[taskName] = { + plugin, + conflicting: conflicting.concat(entryPoint) + } + } else { + config.tasks[taskName] = entryPoint + } + } + } +} From e971ea2e9ad167b7572d289d33526cd47ed0cae3 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 14:24:29 +0000 Subject: [PATCH 068/321] refactor: add a type parameter to HookInstallation --- lib/types/src/hook.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/types/src/hook.ts b/lib/types/src/hook.ts index c63fb79a7..9eb043636 100644 --- a/lib/types/src/hook.ts +++ b/lib/types/src/hook.ts @@ -5,8 +5,8 @@ import { z } from 'zod' import { Plugin } from './index' import { Conflict, isConflict } from './conflict' -export interface HookInstallation { - options: Record +export interface HookInstallation> { + options: Options plugin: Plugin forHook: string hookConstructor: HookConstructor From d65ba30112d459bea901140ea9fd597b79f0df89 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 5 Dec 2023 12:17:45 +0000 Subject: [PATCH 069/321] test: write failing tests for expected PackageJson.mergeChildeInstallations behaviour --- plugins/package-json-hook/test/index.test.ts | 185 ++++++++++++++++++- 1 file changed, 184 insertions(+), 1 deletion(-) diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 7df60062e..4114500c0 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -1,8 +1,10 @@ import { describe, it, expect } from '@jest/globals' import * as path from 'path' import { promises as fs } from 'fs' -import PackageJson from '../src/package-json-helper' +import PackageJson, { PackageJsonState } from '../src/package-json-helper' import winston, { Logger } from 'winston' +import { HookConstructor, HookInstallation } from '@dotcom-tool-kit/types' +import { PackageJsonSchema } from '@dotcom-tool-kit/types/lib/schema/hooks/package-json' const logger = (winston as unknown) as Logger @@ -147,4 +149,185 @@ describe('package.json hook', () => { } }) }) + + describe('conflict resolution', () => { + it('should merge children setting different fields', () => { + const childInstallations = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:local' + } + } + }, + { + plugin: { id: 'c', root: 'plugins/c' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + another: { + field: 'something:else' + } + } + } + ] + const plugin = { id: 'p', root: 'plugins/p' } + + expect( + PackageJson.mergeChildInstallations(plugin, (childInstallations as unknown) as HookInstallation[]) + ).toEqual([ + { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local', + build: 'build:local' + }, + another: { + field: 'something:else' + } + } + } + ]) + }) + + it('should conflict sibling plugins setting the same field', () => { + const childInstallations = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:ci' + } + } + } + ] + + const plugin = { id: 'p', root: 'plugins/p' } + + expect( + PackageJson.mergeChildInstallations(plugin, (childInstallations as unknown) as HookInstallation[]) + ).toEqual([ + { + plugin, + conflicting: childInstallations + } + ]) + }) + + it('should split conflicting and non-conflicting sibling plugins', () => { + const childInstallations = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:ci' + } + } + }, + { + plugin: { id: 'c', root: 'plugins/c' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:local' + } + } + }, + { + plugin: { id: 'd', root: 'plugins/d' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + start: 'run:local' + } + } + } + ] + + const plugin = { id: 'p', root: 'plugins/p' } + + expect( + PackageJson.mergeChildInstallations(plugin, (childInstallations as unknown) as HookInstallation[]) + ).toEqual([ + { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:local', + start: 'run:local' + } + } + }, + { + plugin, + conflicting: [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:ci' + } + } + } + ] + } + ]) + }) + }) }) From 7a4acdf7dd5f9c1b822e4c2c537cd37398e7c423 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 5 Dec 2023 15:59:16 +0000 Subject: [PATCH 070/321] test: add failing tests for expected PackageJson.overrideChildInstallations behaviour --- plugins/package-json-hook/test/index.test.ts | 178 +++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 4114500c0..6aca67dbd 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -329,5 +329,183 @@ describe('package.json hook', () => { } ]) }) + + it('should merge parent and child installations, preferring parent', () => { + const plugin = { id: 'p', root: 'plugins/p' } + + const parentInstallation = { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + } + + const childInstallations = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:ci' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + another: { + field: 'something:else' + } + } + } + ] + + expect( + PackageJson.overrideChildInstallations( + plugin, + (parentInstallation as unknown) as HookInstallation, + (childInstallations as unknown) as HookInstallation[] + ) + ).toEqual([ + { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + }, + another: { + field: 'something:else' + } + } + } + ]) + }) + + it(`should override conflicts that are solved by the parent`, () => { + const plugin = { id: 'p', root: 'plugins/p' } + + const parentInstallation = { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + } + + const childInstallations = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:ci' + } + } + } + ] + + expect( + PackageJson.overrideChildInstallations( + plugin, + (parentInstallation as unknown) as HookInstallation, + (childInstallations as unknown) as HookInstallation[] + ) + ).toEqual([ + { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + } + ]) + }) + + it(`should keep conflicts that aren't solved by the parent`, () => { + const plugin = { id: 'p', root: 'plugins/p' } + + const parentInstallation = { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + } + + const childInstallations = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:ci' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:local' + } + } + } + ] + + expect( + PackageJson.overrideChildInstallations( + plugin, + (parentInstallation as unknown) as HookInstallation, + (childInstallations as unknown) as HookInstallation[] + ) + ).toEqual([ + { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + }, + { + plugin, + conflicting: childInstallations + } + ]) + }) }) }) From 2cc1270a0cec9aa18e73783d4d738ad9937460e8 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 15:41:06 +0000 Subject: [PATCH 071/321] feat: implement PackageJsonHook.mergeChildInstallations --- lib/types/src/hook.ts | 4 +- .../src/package-json-helper.ts | 88 ++++++++++++++++++- plugins/package-json-hook/test/index.test.ts | 31 ++++--- 3 files changed, 110 insertions(+), 13 deletions(-) diff --git a/lib/types/src/hook.ts b/lib/types/src/hook.ts index 9eb043636..91fd9a2cd 100644 --- a/lib/types/src/hook.ts +++ b/lib/types/src/hook.ts @@ -63,6 +63,8 @@ export abstract class Hook): Hook } +export type HookConstructor = { + new (logger: Logger, id: string, options: z.output): Hook +} export type HookClass = HookConstructor & typeof Hook diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index 573542111..5ac343fe7 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -1,12 +1,15 @@ import { z } from 'zod' -import { Hook } from '@dotcom-tool-kit/types' +import { Hook, HookInstallation, Plugin } from '@dotcom-tool-kit/types' import fs from 'fs' import get from 'lodash/get' import set from 'lodash/set' +import partition from 'lodash/partition' import update from 'lodash/update' +import merge from 'lodash/merge' import path from 'path' import { PackageJsonSchema } from '@dotcom-tool-kit/types/lib/schema/hooks/package-json' +import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' interface PackageJsonContents { [field: string]: PackageJsonContents | string @@ -22,6 +25,42 @@ interface PackageJsonState { [path: string]: PackageJsonStateValue } +function installationsOverlap( + installation: HookInstallation>, + other: HookInstallation> +): boolean { + for (const [field, object] of Object.entries(installation.options)) { + for (const key of Object.keys(object)) { + if (field in other.options && key in other.options[field]) { + return true + } + } + } + + return false +} + +function partitionInstallations( + installation: HookInstallation>, + mergeable: HookInstallation>[], + unmergeable: HookInstallation>[] +): [ + HookInstallation>[], + HookInstallation>[] +] { + const [noLongerMergeable, stillMergeable] = partition(mergeable, (other) => + installationsOverlap(installation, other) + ) + + const overlapsWithUnmergeable = unmergeable.some((other) => installationsOverlap(installation, other)) + + if (noLongerMergeable.length > 0 || overlapsWithUnmergeable) { + return [stillMergeable, [...unmergeable, ...noLongerMergeable, installation]] + } + + return [[...stillMergeable, installation], unmergeable] +} + export default class PackageJson extends Hook { private _packageJson?: PackageJsonContents @@ -29,6 +68,53 @@ export default class PackageJson extends Hook> + | Conflict>> + )[] + ): (HookInstallation> | Conflict)[] { + let mergeable: HookInstallation>[] = [] + let unmergeable: HookInstallation>[] = [] + + for (const installation of childInstallations) { + if (isConflict(installation)) { + unmergeable.push(...installation.conflicting) + } else { + [mergeable, unmergeable] = partitionInstallations(installation, mergeable, unmergeable) + } + } + + const results: (HookInstallation> | Conflict)[] = [] + + if (mergeable.length > 0) { + results.push({ + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: merge({}, ...mergeable.map((installation) => installation.options)) + }) + } + + if (unmergeable.length > 0) { + results.push({ + plugin, + conflicting: unmergeable + }) + } + + return results + } + + static overrideChildInstallations( + plugin: Plugin, + parentInstallation: HookInstallation, + _childInstallations: (HookInstallation | Conflict)[] + ): (HookInstallation | Conflict)[] { + return [parentInstallation] + } + async getPackageJson(): Promise { if (!this._packageJson) { const rawPackageJson = await fs.promises.readFile(this.filepath, 'utf8') diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 6aca67dbd..048924b2f 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -1,9 +1,9 @@ import { describe, it, expect } from '@jest/globals' import * as path from 'path' import { promises as fs } from 'fs' -import PackageJson, { PackageJsonState } from '../src/package-json-helper' +import PackageJson from '../src/package-json-helper' import winston, { Logger } from 'winston' -import { HookConstructor, HookInstallation } from '@dotcom-tool-kit/types' +import { HookInstallation } from '@dotcom-tool-kit/types' import { PackageJsonSchema } from '@dotcom-tool-kit/types/lib/schema/hooks/package-json' const logger = (winston as unknown) as Logger @@ -187,7 +187,10 @@ describe('package.json hook', () => { const plugin = { id: 'p', root: 'plugins/p' } expect( - PackageJson.mergeChildInstallations(plugin, (childInstallations as unknown) as HookInstallation[]) + PackageJson.mergeChildInstallations( + plugin, + (childInstallations as unknown) as HookInstallation>[] + ) ).toEqual([ { plugin, @@ -233,7 +236,10 @@ describe('package.json hook', () => { const plugin = { id: 'p', root: 'plugins/p' } expect( - PackageJson.mergeChildInstallations(plugin, (childInstallations as unknown) as HookInstallation[]) + PackageJson.mergeChildInstallations( + plugin, + (childInstallations as unknown) as HookInstallation>[] + ) ).toEqual([ { plugin, @@ -289,7 +295,10 @@ describe('package.json hook', () => { const plugin = { id: 'p', root: 'plugins/p' } expect( - PackageJson.mergeChildInstallations(plugin, (childInstallations as unknown) as HookInstallation[]) + PackageJson.mergeChildInstallations( + plugin, + (childInstallations as unknown) as HookInstallation>[] + ) ).toEqual([ { plugin, @@ -370,8 +379,8 @@ describe('package.json hook', () => { expect( PackageJson.overrideChildInstallations( plugin, - (parentInstallation as unknown) as HookInstallation, - (childInstallations as unknown) as HookInstallation[] + (parentInstallation as unknown) as HookInstallation>, + (childInstallations as unknown) as HookInstallation>[] ) ).toEqual([ { @@ -430,8 +439,8 @@ describe('package.json hook', () => { expect( PackageJson.overrideChildInstallations( plugin, - (parentInstallation as unknown) as HookInstallation, - (childInstallations as unknown) as HookInstallation[] + (parentInstallation as unknown) as HookInstallation>, + (childInstallations as unknown) as HookInstallation>[] ) ).toEqual([ { @@ -487,8 +496,8 @@ describe('package.json hook', () => { expect( PackageJson.overrideChildInstallations( plugin, - (parentInstallation as unknown) as HookInstallation, - (childInstallations as unknown) as HookInstallation[] + (parentInstallation as unknown) as HookInstallation>, + (childInstallations as unknown) as HookInstallation>[] ) ).toEqual([ { From 74768458a8c7c8b8a34ada25cfaa4e0569e82069 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 15:56:55 +0000 Subject: [PATCH 072/321] test: update overrideChildInstallations test cases to be closer to real life --- plugins/package-json-hook/test/index.test.ts | 183 ++++++++++++++++--- 1 file changed, 153 insertions(+), 30 deletions(-) diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 048924b2f..ab544a583 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -361,14 +361,7 @@ describe('package.json hook', () => { options: { scripts: { test: 'test:ci' - } - } - }, - { - plugin: { id: 'b', root: 'plugins/b' }, - forHook: 'PackageJson', - hookConstructor: PackageJson, - options: { + }, another: { field: 'something:else' } @@ -415,7 +408,41 @@ describe('package.json hook', () => { const childInstallations = [ { - plugin: { id: 'a', root: 'plugins/a' }, + plugin: { id: 'c', root: 'plugins/c' }, + conflicting: [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:ci' + } + } + } + ] + } + ] + + expect( + PackageJson.overrideChildInstallations( + plugin, + (parentInstallation as unknown) as HookInstallation>, + (childInstallations as unknown) as HookInstallation>[] + ) + ).toEqual([ + { + plugin, forHook: 'PackageJson', hookConstructor: PackageJson, options: { @@ -423,16 +450,49 @@ describe('package.json hook', () => { test: 'test:local' } } - }, + } + ]) + }) + + it(`should keep conflicts that aren't solved by the parent`, () => { + const plugin = { id: 'p', root: 'plugins/p' } + + const parentInstallation = { + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + } + + const childInstallations = [ { - plugin: { id: 'b', root: 'plugins/b' }, - forHook: 'PackageJson', - hookConstructor: PackageJson, - options: { - scripts: { - test: 'test:ci' + plugin: { id: 'c', root: 'plugins/c' }, + conflicting: [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:ci' + } + } } - } + ] } ] @@ -452,11 +512,15 @@ describe('package.json hook', () => { test: 'test:local' } } + }, + { + plugin: { id: 'p', root: 'plugins/p' }, + conflicting: childInstallations[0].conflicting } ]) }) - it(`should keep conflicts that aren't solved by the parent`, () => { + it(`should basically be god`, () => { const plugin = { id: 'p', root: 'plugins/p' } const parentInstallation = { @@ -472,24 +536,59 @@ describe('package.json hook', () => { const childInstallations = [ { - plugin: { id: 'a', root: 'plugins/a' }, + plugin: { id: 'd', root: 'plugins/d' }, forHook: 'PackageJson', hookConstructor: PackageJson, options: { - scripts: { - build: 'build:ci' + another: { + field: 'something:else' } } }, { - plugin: { id: 'b', root: 'plugins/b' }, - forHook: 'PackageJson', - hookConstructor: PackageJson, - options: { - scripts: { - build: 'build:local' + plugin: { id: 'c', root: 'plugins/c' }, + conflicting: [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:ci' + } + } + }, + { + plugin: { id: 'e', root: 'plugins/e' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:local' + } + } + }, + { + plugin: { id: 'f', root: 'plugins/f' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + test: 'test:ci' + } + } } - } + ] } ] @@ -507,12 +606,36 @@ describe('package.json hook', () => { options: { scripts: { test: 'test:local' + }, + another: { + field: 'something:else' } } }, { - plugin, - conflicting: childInstallations + plugin: { id: 'p', root: 'plugins/p' }, + conflicting: [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:local' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: { + scripts: { + build: 'build:ci' + } + } + } + ] } ]) }) From eb78da57af4de0c9ef5aa6f91fb25a460ef2a20f Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 19 Dec 2023 17:29:03 +0000 Subject: [PATCH 073/321] feat: implement PackageJson.overrideChildInstallations --- .eslintrc.js | 4 +- .../src/package-json-helper.ts | 75 +++++++++++++------ 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 01b037ab4..4911b0bf5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,7 +15,9 @@ module.exports = { 'no-unused-vars': 'off', // Necessary to allow us to define arguments in a method that only subclasses use // https://github.com/typescript-eslint/typescript-eslint/issues/586#issuecomment-510099609 - '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }] + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], + // Prettier sometimes like inserting semis + '@typescript-eslint/no-extra-semi': 'off' }, overrides: [ { diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index 5ac343fe7..285b4ee5f 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -61,6 +61,32 @@ function partitionInstallations( return [[...stillMergeable, installation], unmergeable] } +function mergeInstallationResults( + plugin: Plugin, + mergeable: HookInstallation>[], + unmergeable: HookInstallation>[] +) { + const results: (HookInstallation> | Conflict)[] = [] + + if (mergeable.length > 0) { + results.push({ + plugin, + forHook: 'PackageJson', + hookConstructor: PackageJson, + options: merge({}, ...mergeable.map((installation) => installation.options)) + }) + } + + if (unmergeable.length > 0) { + results.push({ + plugin, + conflicting: unmergeable + }) + } + + return results +} + export default class PackageJson extends Hook { private _packageJson?: PackageJsonContents @@ -82,37 +108,40 @@ export default class PackageJson extends Hook> | Conflict)[] = [] + return mergeInstallationResults(plugin, mergeable, unmergeable) + } - if (mergeable.length > 0) { - results.push({ - plugin, - forHook: 'PackageJson', - hookConstructor: PackageJson, - options: merge({}, ...mergeable.map((installation) => installation.options)) - }) - } + static overrideChildInstallations( + plugin: Plugin, + parentInstallation: HookInstallation>, + childInstallations: ( + | HookInstallation> + | Conflict>> + )[] + ): (HookInstallation> | Conflict)[] { + const mergeable: HookInstallation>[] = [] + const unmergeable: HookInstallation>[] = [] - if (unmergeable.length > 0) { - results.push({ - plugin, - conflicting: unmergeable - }) + for (const installation of childInstallations) { + if (isConflict(installation)) { + const [canHandle, cannotHandle] = partition(installation.conflicting, (other) => + installationsOverlap(parentInstallation, other) + ) + + mergeable.push(...canHandle) + unmergeable.push(...cannotHandle) + } else { + mergeable.push(installation) + } } - return results - } + mergeable.push(parentInstallation) - static overrideChildInstallations( - plugin: Plugin, - parentInstallation: HookInstallation, - _childInstallations: (HookInstallation | Conflict)[] - ): (HookInstallation | Conflict)[] { - return [parentInstallation] + return mergeInstallationResults(plugin, mergeable, unmergeable) } async getPackageJson(): Promise { From f398f15413b024ed096e707555090f040e27aa22 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 20 Dec 2023 13:02:27 +0000 Subject: [PATCH 074/321] test: less whimsical test name Co-authored-by: Ivo Murrell --- plugins/package-json-hook/test/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index ab544a583..474b724d9 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -520,7 +520,7 @@ describe('package.json hook', () => { ]) }) - it(`should basically be god`, () => { + it(`should partially override only the conflicts solvable by the parent`, () => { const plugin = { id: 'p', root: 'plugins/p' } const parentInstallation = { From 4cc08332cd4901c66c482d72c252a7053b6641ce Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 21 Dec 2023 13:32:49 +0000 Subject: [PATCH 075/321] feat: add a Base subclass for init functions --- core/cli/src/init.ts | 0 lib/types/src/index.ts | 1 + lib/types/src/init.ts | 22 ++++++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 core/cli/src/init.ts create mode 100644 lib/types/src/init.ts diff --git a/core/cli/src/init.ts b/core/cli/src/init.ts new file mode 100644 index 000000000..e69de29bb diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 9c1699881..21cdeab7c 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -6,6 +6,7 @@ export * from './validated' export * from './base' export * from './task' export * from './hook' +export * from './init' export type RCFile = { plugins: string[] diff --git a/lib/types/src/init.ts b/lib/types/src/init.ts new file mode 100644 index 000000000..f63792b7a --- /dev/null +++ b/lib/types/src/init.ts @@ -0,0 +1,22 @@ +import type { Logger } from 'winston' +import { initSymbol, typeSymbol } from './symbols' +import { Base } from './base' + +export abstract class Init extends Base { + logger: Logger + + constructor(logger: Logger, public id: string) { + super() + this.logger = logger.child({ hook: this.constructor.name }) + } + + static get [typeSymbol](): symbol { + return initSymbol + } + + get [typeSymbol](): symbol { + return initSymbol + } + + abstract init(): Promise +} From f46c5cbaa4905fac55cd368bb8a6f7ef9d388911 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 21 Dec 2023 17:03:30 +0000 Subject: [PATCH 076/321] feat: allow plugins to specify init entrypoints --- core/cli/src/config.ts | 3 ++- core/cli/src/init.ts | 23 +++++++++++++++++++++++ core/cli/src/plugin.ts | 2 ++ core/cli/src/plugin/merge-inits.ts | 13 +++++++++++++ core/cli/src/rc-file.ts | 5 +++-- core/create/src/index.ts | 3 ++- lib/types/src/index.ts | 2 ++ lib/types/src/init.ts | 8 +++++++- lib/types/src/symbols.ts | 1 + 9 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 core/cli/src/plugin/merge-inits.ts diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index b1138366e..32abf6d02 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -32,7 +32,8 @@ export const createConfig = (): RawConfig => ({ tasks: {}, commandTasks: {}, options: {}, - hooks: {} + hooks: {}, + inits: [] }) export function validateConfig(config: ValidPluginsConfig, logger: Logger): ValidConfig { diff --git a/core/cli/src/init.ts b/core/cli/src/init.ts index e69de29bb..ef29a0332 100644 --- a/core/cli/src/init.ts +++ b/core/cli/src/init.ts @@ -0,0 +1,23 @@ +import { HookClass, Init, InitClass, ValidConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' +import { Logger } from 'winston' +import { importEntryPoint } from './plugin/entry-point' + +const loadInitEntrypoints = async (logger: Logger, config: ValidConfig): Promise> => { + const initClassResults = reduceValidated( + await Promise.all( + config.inits.map(async (entryPoint) => { + const hookResult = await importEntryPoint(Init, entryPoint) + return hookResult.map((initClass) => initClass as InitClass) + }) + ) + ) + + return initClassResults.map((initClasses) => initClasses.map((initClass) => new initClass(logger))) +} + +export async function runInit(logger: Logger, config: ValidConfig): Promise { + const initResults = await loadInitEntrypoints(logger, config) + const inits = initResults.unwrap('plugin initialisation classes were invalid!') + + await Promise.all(inits.map(async (init) => init.init())) +} diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 8e9d8a090..c94c2519f 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -20,6 +20,7 @@ import { mergePluginTasks } from './plugin/merge-tasks' import { mergePluginHooks } from './plugin/merge-hooks' import { mergePluginCommands } from './plugin/merge-commands' import { mergePluginOptions } from './plugin/merge-options' +import { mergePluginInits } from './plugin/merge-inits' export async function loadPlugin( id: string, @@ -87,6 +88,7 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger mergePluginHooks(config, plugin) mergePluginCommands(config, plugin) mergePluginOptions(config, plugin) + mergePluginInits(config, plugin) config.resolvedPlugins.add(plugin.id) } diff --git a/core/cli/src/plugin/merge-inits.ts b/core/cli/src/plugin/merge-inits.ts new file mode 100644 index 000000000..7baf44dbe --- /dev/null +++ b/core/cli/src/plugin/merge-inits.ts @@ -0,0 +1,13 @@ +import { Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' + +export const mergePluginInits = (config: ValidPluginsConfig, plugin: Plugin) => { + if (plugin.rcFile) { + // no conflict resolution needed; we'll just run them all ig + config.inits.push( + ...plugin.rcFile.init.map((init) => ({ + plugin, + modulePath: init + })) + ) + } +} diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 4ca3d8197..b2c75b420 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -5,7 +5,7 @@ import * as path from 'path' import type { Logger } from 'winston' export const explorer = cosmiconfig('toolkit', { ignoreEmptySearchPlaces: false }) -const emptyConfig = { plugins: [], installs: {}, tasks: {}, commands: {}, options: {}, hooks: [] } +const emptyConfig = { plugins: [], installs: {}, tasks: {}, commands: {}, options: {}, hooks: [], init: [] } let rootConfig: string | undefined type RawRCFile = { @@ -39,6 +39,7 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo tasks: config.tasks ?? {}, commands: config.commands ?? {}, options: config.options ?? {}, - hooks: config.hooks ?? [] + hooks: config.hooks ?? [], + init: config.init ?? [] } } diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 5a17e44f7..5669af864 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -117,7 +117,8 @@ async function main() { tasks: {}, commands: {}, options: {}, - hooks: [] + hooks: [], + init: [] } const originalCircleConfig = await fsp.readFile(circleConfigPath, 'utf8').catch(() => undefined) diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 21cdeab7c..0636c210f 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -15,6 +15,7 @@ export type RCFile = { commands: { [id: string]: string | string[] } options: { [id: string]: Record } hooks: { [id: string]: Record }[] + init: string[] } export interface Plugin { @@ -50,6 +51,7 @@ export interface RawConfig { commandTasks: { [id: string]: CommandTask | Conflict } options: { [id: string]: PluginOptions | Conflict | undefined } hooks: { [id: string]: EntryPoint | Conflict } + inits: EntryPoint[] } export type ValidPluginsConfig = Omit & { diff --git a/lib/types/src/init.ts b/lib/types/src/init.ts index f63792b7a..42b99279f 100644 --- a/lib/types/src/init.ts +++ b/lib/types/src/init.ts @@ -5,7 +5,7 @@ import { Base } from './base' export abstract class Init extends Base { logger: Logger - constructor(logger: Logger, public id: string) { + constructor(logger: Logger) { super() this.logger = logger.child({ hook: this.constructor.name }) } @@ -20,3 +20,9 @@ export abstract class Init extends Base { abstract init(): Promise } + +export type InitConstructor = { + new (logger: Logger): Init +} + +export type InitClass = InitConstructor & typeof Init diff --git a/lib/types/src/symbols.ts b/lib/types/src/symbols.ts index 63cc91965..79ba26163 100644 --- a/lib/types/src/symbols.ts +++ b/lib/types/src/symbols.ts @@ -8,3 +8,4 @@ export const typeSymbol = Symbol.for('@dotcom-tool-kit/types') export const baseSymbol = Symbol.for('@dotcom-tool-kit/types/base') export const taskSymbol = Symbol.for('@dotcom-tool-kit/types/task') export const hookSymbol = Symbol.for('@dotcom-tool-kit/types/hook') +export const initSymbol = Symbol.for('@dotcom-tool-kit/types/init') From 1420ca633549ade9a86f8376048786bd07fd6df6 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 21 Dec 2023 17:05:43 +0000 Subject: [PATCH 077/321] refactor: turn the old circleci entrypoint into an init --- plugins/circleci/.toolkitrc.yml | 3 +++ plugins/circleci/src/index.ts | 20 -------------------- plugins/circleci/src/init-env-vars.ts | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 20 deletions(-) delete mode 100644 plugins/circleci/src/index.ts create mode 100644 plugins/circleci/src/init-env-vars.ts diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index 0d63d15d1..eaa915321 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -1,2 +1,5 @@ installs: CircleCiConfig: './lib/circleci-config' + +init: + - './lib/init-env-vars' diff --git a/plugins/circleci/src/index.ts b/plugins/circleci/src/index.ts deleted file mode 100644 index ce61f4528..000000000 --- a/plugins/circleci/src/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { writeState } from '@dotcom-tool-kit/state' - -const envVars = { - branch: process.env.CIRCLE_BRANCH, - repo: process.env.CIRCLE_PROJECT_REPONAME, - version: process.env.CIRCLE_SHA1, - tag: process.env.CIRCLE_TAG -} - -function pluginInit() { - if (process.env.CIRCLECI) { - /* eslint-disable-next-line no-console -- - * cannot use winston logging during module initialisation - **/ - console.log(`writing circle ci environment variables to state...`) - writeState('ci', envVars) - } -} - -pluginInit() diff --git a/plugins/circleci/src/init-env-vars.ts b/plugins/circleci/src/init-env-vars.ts new file mode 100644 index 000000000..50b78cdfb --- /dev/null +++ b/plugins/circleci/src/init-env-vars.ts @@ -0,0 +1,18 @@ +import { writeState } from '@dotcom-tool-kit/state' +import { Init } from '@dotcom-tool-kit/types' + +export default class CircleCIEnvVars extends Init { + async init() { + const envVars = { + branch: process.env.CIRCLE_BRANCH, + repo: process.env.CIRCLE_PROJECT_REPONAME, + version: process.env.CIRCLE_SHA1, + tag: process.env.CIRCLE_TAG + } + + if (process.env.CIRCLECI) { + this.logger.info(`writing circle ci environment variables to state...`) + writeState('ci', envVars) + } + } +} From 80b673f2d8f3f155ab354a95128c4454afa4e64a Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 21 Dec 2023 17:08:57 +0000 Subject: [PATCH 078/321] feat: run init classes before install and runTasks --- core/cli/src/install.ts | 7 +++++-- core/cli/src/tasks.ts | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index ea551ea26..284d6c393 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -19,6 +19,7 @@ import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/types/src/conf import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' import { formatUninstalledHooks } from './messages' import { importEntryPoint } from './plugin/entry-point' +import { runInit } from './init' // implementation of the Array#every method that supports asynchronous predicates async function asyncEvery(arr: T[], pred: (x: T) => Promise): Promise { @@ -112,11 +113,13 @@ export default async function installHooks(logger: Logger): Promise } } + await runInit(logger, config) + const errors: Error[] = [] - // group hooks without an installGroup separately so that their check() - // method runs independently const hooks = (await loadHookInstallations(logger, config)).unwrap('hooks are invalid') + // group hooks without an installGroup separately so that their check() + // method runs independently const groups = groupBy(hooks, (hook) => hook.installGroup ?? '__' + hook.id) for (const group of Object.values(groups)) { try { diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 75a762fa9..478ac6b7a 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -7,6 +7,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { checkInstall } from './install' import { styles } from '@dotcom-tool-kit/logger' import { shouldDisableNativeFetch } from './fetch' +import { runInit } from './init' type ErrorSummary = { hook: string @@ -63,6 +64,7 @@ ${availableHooks}` } } + await runInit(logger, config) await checkInstall(logger, config) if (shouldDisableNativeFetch()) { From 97f0cb77dcceb3828b051e10bc7d03e2ed2c9777 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 4 Jan 2024 17:09:59 +0000 Subject: [PATCH 079/321] refactor: simpler inits casting Co-authored-by: Ivo Murrell --- core/cli/src/init.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/core/cli/src/init.ts b/core/cli/src/init.ts index ef29a0332..e5ba395a5 100644 --- a/core/cli/src/init.ts +++ b/core/cli/src/init.ts @@ -4,12 +4,7 @@ import { importEntryPoint } from './plugin/entry-point' const loadInitEntrypoints = async (logger: Logger, config: ValidConfig): Promise> => { const initClassResults = reduceValidated( - await Promise.all( - config.inits.map(async (entryPoint) => { - const hookResult = await importEntryPoint(Init, entryPoint) - return hookResult.map((initClass) => initClass as InitClass) - }) - ) + await Promise.all(config.inits.map((entryPoint) => importEntryPoint(Init as InitClass, entryPoint))) ) return initClassResults.map((initClasses) => initClasses.map((initClass) => new initClass(logger))) From 68704a8653ef046f2c19b44a94d41b0b6ca5abca Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 21 Dec 2023 17:08:57 +0000 Subject: [PATCH 080/321] feat: run init classes before install and runTasks --- core/cli/src/tasks.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 478ac6b7a..60d25df1a 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -66,6 +66,7 @@ ${availableHooks}` await runInit(logger, config) await checkInstall(logger, config) + await runInit(logger, config) if (shouldDisableNativeFetch()) { process.execArgv.push('--no-experimental-fetch') From 4068b371b4ddcac10302412132665b0f7cd3c7a2 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 11:52:29 +0000 Subject: [PATCH 081/321] feat: move validated into its own package --- core/cli/package.json | 1 + core/cli/src/config/validate-plugins.ts | 3 +- core/cli/src/init.ts | 3 +- core/cli/src/install.ts | 11 +-- core/cli/src/plugin.ts | 15 +---- core/cli/src/plugin/entry-point.ts | 3 +- core/cli/src/tasks.ts | 3 +- core/cli/tsconfig.json | 7 +- lib/types/package.json | 1 + lib/types/src/base.ts | 2 +- lib/types/src/index.ts | 4 +- lib/types/tsconfig.json | 3 + lib/validated/README.md | 67 +++++++++++++++++++ lib/validated/jest.config.js | 5 ++ lib/validated/package.json | 14 ++++ .../validated.ts => validated/src/index.ts} | 0 lib/validated/tsconfig.json | 12 ++++ package-lock.json | 14 ++++ 18 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 lib/validated/README.md create mode 100644 lib/validated/jest.config.js create mode 100644 lib/validated/package.json rename lib/{types/src/validated.ts => validated/src/index.ts} (100%) create mode 100644 lib/validated/tsconfig.json diff --git a/core/cli/package.json b/core/cli/package.json index d9a91f7e2..92327a44f 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -44,6 +44,7 @@ "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/validated": "^1.0.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "cosmiconfig": "^7.0.0", "lodash": "^4.17.21", diff --git a/core/cli/src/config/validate-plugins.ts b/core/cli/src/config/validate-plugins.ts index 320ac1b18..ebfe13ef4 100644 --- a/core/cli/src/config/validate-plugins.ts +++ b/core/cli/src/config/validate-plugins.ts @@ -1,4 +1,5 @@ -import { RawConfig, ValidPluginsConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' +import { RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' export function validatePlugins(config: RawConfig): Validated { const validatedPlugins = reduceValidated( diff --git a/core/cli/src/init.ts b/core/cli/src/init.ts index e5ba395a5..5f46d1096 100644 --- a/core/cli/src/init.ts +++ b/core/cli/src/init.ts @@ -1,4 +1,5 @@ -import { HookClass, Init, InitClass, ValidConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' +import { Init, InitClass, ValidConfig } from '@dotcom-tool-kit/types' +import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' import { Logger } from 'winston' import { importEntryPoint } from './plugin/entry-point' diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 284d6c393..4fe1be87e 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -5,15 +5,8 @@ import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' import { loadConfig } from './config' import { hasConfigChanged, updateHashes } from './config/hash' -import { - Hook, - HookClass, - ValidConfig, - Validated, - invalid, - reduceValidated, - valid -} from '@dotcom-tool-kit/types' +import { Hook, HookClass, ValidConfig } from '@dotcom-tool-kit/types' +import { Validated, invalid, reduceValidated, valid } from '@dotcom-tool-kit/validated' import { reducePluginHookInstallations } from './plugin/reduce-installations' import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/types/src/conflict' import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index c94c2519f..a8bd37462 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,19 +1,8 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import { - CommandTask, - EntryPoint, - invalid, - Plugin, - PluginOptions, - RawConfig, - reduceValidated, - valid, - Validated, - ValidPluginsConfig -} from '@dotcom-tool-kit/types' +import { Plugin, RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { invalid, reduceValidated, valid, Validated } from '@dotcom-tool-kit/validated' import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' -import { Conflict, isConflict } from '@dotcom-tool-kit/types/lib/conflict' import { loadToolKitRC } from './rc-file' import { indentReasons } from './messages' import { mergePluginTasks } from './plugin/merge-tasks' diff --git a/core/cli/src/plugin/entry-point.ts b/core/cli/src/plugin/entry-point.ts index 768d23df0..6413fc8fd 100644 --- a/core/cli/src/plugin/entry-point.ts +++ b/core/cli/src/plugin/entry-point.ts @@ -1,6 +1,7 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import { Base, EntryPoint, Validated, invalid } from '@dotcom-tool-kit/types' +import { Base, EntryPoint } from '@dotcom-tool-kit/types' +import { Validated, invalid } from '@dotcom-tool-kit/validated' import resolvePkg from 'resolve-pkg' import { isPlainObject } from 'lodash' import { indentReasons } from '../messages' diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 60d25df1a..47ee5b7b7 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -1,4 +1,5 @@ -import { Task, TaskConstructor, ValidConfig, Validated, reduceValidated } from '@dotcom-tool-kit/types' +import { Task, TaskConstructor, ValidConfig } from '@dotcom-tool-kit/types' +import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' import type { Logger } from 'winston' import { importEntryPoint } from './plugin/entry-point' import { OptionKey, getOptions, setOptions } from '@dotcom-tool-kit/options' diff --git a/core/cli/tsconfig.json b/core/cli/tsconfig.json index b78cb0552..2b448aa0c 100644 --- a/core/cli/tsconfig.json +++ b/core/cli/tsconfig.json @@ -12,13 +12,14 @@ }, { "path": "../../lib/types" + }, + { + "path": "../../lib/validated" } ], "compilerOptions": { "outDir": "lib", "rootDir": "src" }, - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/lib/types/package.json b/lib/types/package.json index 95b4e99f7..0c443284c 100644 --- a/lib/types/package.json +++ b/lib/types/package.json @@ -25,6 +25,7 @@ "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/validated": "^1.0.0", "semver": "^7.3.7", "tslib": "^2.3.1", "zod": "^3.20.2" diff --git a/lib/types/src/base.ts b/lib/types/src/base.ts index 70e267707..361fc3402 100644 --- a/lib/types/src/base.ts +++ b/lib/types/src/base.ts @@ -2,7 +2,7 @@ import { styles as s } from '@dotcom-tool-kit/logger' import path from 'path' import fs from 'fs' import { baseSymbol, typeSymbol } from './symbols' -import { Validated, invalid, valid } from './validated' +import { Validated, invalid, valid } from '@dotcom-tool-kit/validated' import semver from 'semver' const packageJsonPath = path.resolve(__dirname, '../package.json') diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 0636c210f..f181a6dfb 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -1,8 +1,8 @@ import type { Conflict } from './conflict' -import type { Validated } from './validated' +import type { Validated } from '@dotcom-tool-kit/validated' import type { Options as SchemaOptions } from './plugins' -export * from './validated' +export * from '@dotcom-tool-kit/validated' export * from './base' export * from './task' export * from './hook' diff --git a/lib/types/tsconfig.json b/lib/types/tsconfig.json index 917152a25..547a1f2d1 100644 --- a/lib/types/tsconfig.json +++ b/lib/types/tsconfig.json @@ -6,6 +6,9 @@ }, { "path": "../logger" + }, + { + "path": "../validated" } ], "compilerOptions": { diff --git a/lib/validated/README.md b/lib/validated/README.md new file mode 100644 index 000000000..efa62b822 --- /dev/null +++ b/lib/validated/README.md @@ -0,0 +1,67 @@ +# `@dotcom-tool-kit/validated` + +Types and functions for an errors-as-first-class-values pattern + +## Rationale + +In Tool Kit, we handle loading many plugins with different types of entry point (for `Task`s, `Hook`s etc) in parallel. There are various points this process could go wrong: importing an entry point, checking version compatibility, and more. + +If we naïvely used exception throwing or Promise rejections, Tool Kit would stop at the first problem that happened; the user would fix that only to run into the next error, which would be frustrating. We want to get as far as we can and collect all the errors that happen to present _once_, as late as possible. + +We _could_ still use exceptions/rejections for this, along with `Promise.allSettled`. However, with that pattern it would be difficult to follow the data flow of the errors, and easy to accidentally forget to collate some errors, falling into the same issue of throwing one error at a time. + +Instead, we model these errors using an explicit return value, `Validated`. This type is a union of `Valid` which represents a correct value, and `Invalid` which represents a problem with a list of `string` reasons. By making this an explicit type, we clearly mark all the functions that can return errors we may want to collate, and make it impossible to use the values without deciding what to do with the errors. + +This pattern is modelled after Go's [error handling using multiple return values](https://go.dev/doc/tutorial/handle-errors), Rust's [`Result` type](https://doc.rust-lang.org/book/ch09-00-error-handling.html) and Haskell's [`Either a b` type](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Either.html). + +## Usage + +### Creating a `Validated` + +`@dotcom-tool-kit/validated` exports two constructor functions, `valid` and `invalid`. Use these to create a wrapper when the status of the value is known, e.g.: + +```typescript +valid({ some: 'object' }) + +invalid([ + 'list of problems' +]) +``` + +### Using `Validated` values + +`Validated` objects have methods that are similar to the Array or Promise methods, allowing you to do things with the values or error reasons without having to inspect the types: + +```typescript +validated.map(value => { + // do something with value + return // something else. replaces the value with this return value if valid, does nothing if invalid +}) + +validated.mapReasons(reasons => { + // do something with value + return // something else. replaces the reasons with this return value if invalid, does nothing if valid +}) +``` + +### Extracting values from a `Validated` + +`Validated` has an `.unwrap` method that allows you to extract its value if valid, or throws an error with its reasons if invalid. This should be used as late as possible, when you can't get any further without the value, and need to stop if it's invalid. + +```typescript +validated.unwrap('something was invalid!') +``` + +### Grouping an array of `Validated` + +Similar to `Promise.all`, if you have multiple `Validated`s and you need to group their values and reasons (i.e. you have `Array>` and you want `Validated>`), we have `reduceValidated`: + +```typescript +reduceValidated([ + validated1, + validated2, + validated3 +]) +``` + +This is used in Tool Kit when e.g. we load multiple plugins in parallel. diff --git a/lib/validated/jest.config.js b/lib/validated/jest.config.js new file mode 100644 index 000000000..24889bbe6 --- /dev/null +++ b/lib/validated/jest.config.js @@ -0,0 +1,5 @@ +const base = require('../../jest.config.base') + +module.exports = { + ...base +} diff --git a/lib/validated/package.json b/lib/validated/package.json new file mode 100644 index 000000000..2fae62067 --- /dev/null +++ b/lib/validated/package.json @@ -0,0 +1,14 @@ +{ + "name": "@dotcom-tool-kit/validated", + "version": "1.0.0", + "description": "", + "main": "lib", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/error": "^3.1.0" + } +} diff --git a/lib/types/src/validated.ts b/lib/validated/src/index.ts similarity index 100% rename from lib/types/src/validated.ts rename to lib/validated/src/index.ts diff --git a/lib/validated/tsconfig.json b/lib/validated/tsconfig.json new file mode 100644 index 000000000..de4070b0a --- /dev/null +++ b/lib/validated/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.settings.json", + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + }, + "references": [ + { + "path": "../error" + } + ] +} diff --git a/package-lock.json b/package-lock.json index bb3a580ad..4e91d6eb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,7 @@ "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/validated": "^1.0.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "cosmiconfig": "^7.0.0", "lodash": "^4.17.21", @@ -1230,6 +1231,7 @@ "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/validated": "^1.0.0", "semver": "^7.3.7", "tslib": "^2.3.1", "zod": "^3.20.2" @@ -1250,6 +1252,13 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, + "lib/validated": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/error": "^3.1.0" + } + }, "lib/vault": { "name": "@dotcom-tool-kit/vault", "version": "3.2.0", @@ -6316,6 +6325,10 @@ "resolved": "plugins/upload-assets-to-s3", "link": true }, + "node_modules/@dotcom-tool-kit/validated": { + "resolved": "lib/validated", + "link": true + }, "node_modules/@dotcom-tool-kit/vault": { "resolved": "lib/vault", "link": true @@ -30122,6 +30135,7 @@ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/package-json-hook": { + "name": "@dotcom-tool-kit/package-json-hook", "version": "4.2.0", "license": "ISC", "dependencies": { From f16563b2d6d13c04c6e72c1626715b80970a6569 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 12:21:16 +0000 Subject: [PATCH 082/321] chore: remove unused validated join method --- lib/validated/src/index.ts | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/validated/src/index.ts b/lib/validated/src/index.ts index f94f2d17e..fc48c251a 100644 --- a/lib/validated/src/index.ts +++ b/lib/validated/src/index.ts @@ -4,7 +4,6 @@ interface Mixin { map(f: (val: T) => U): Validated mapError(f: (reasons: string[]) => string[]): Validated flatMap(f: (val: T) => Validated): Validated - join(other: Validated): Validated<[T, U]> awaitValue(): Promise>> unwrap(message?: string): T } @@ -51,22 +50,6 @@ const mixin = (validated: Invalid | Valid): Validated => ({ } }, - join(other: Validated) { - if (validated.valid) { - if (other.valid) { - return valid([validated.value, other.value]) - } else { - return invalid<[T, U]>(other.reasons) - } - } else { - if (other.valid) { - return mixin<[T, U]>(validated) - } else { - return invalid<[T, U]>([...validated.reasons, ...other.reasons]) - } - } - }, - unwrap(message = '') { if (validated.valid) { return validated.value From 2711baa9c30be063524477bb0cef78746c8e7ee7 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 12:22:33 +0000 Subject: [PATCH 083/321] test: add tests for validated --- lib/validated/README.md | 4 +- lib/validated/test/index.test.ts | 156 +++++++++++++++++++++++++++++++ lib/validated/tsconfig.json | 1 + 3 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 lib/validated/test/index.test.ts diff --git a/lib/validated/README.md b/lib/validated/README.md index efa62b822..325b4aa8e 100644 --- a/lib/validated/README.md +++ b/lib/validated/README.md @@ -38,8 +38,8 @@ validated.map(value => { return // something else. replaces the value with this return value if valid, does nothing if invalid }) -validated.mapReasons(reasons => { - // do something with value +validated.mapError(reasons => { + // do something with reasons return // something else. replaces the reasons with this return value if invalid, does nothing if valid }) ``` diff --git a/lib/validated/test/index.test.ts b/lib/validated/test/index.test.ts new file mode 100644 index 000000000..0c8624cb9 --- /dev/null +++ b/lib/validated/test/index.test.ts @@ -0,0 +1,156 @@ +import { describe, expect, it, test } from '@jest/globals' +import { invalid, reduceValidated, valid } from '../src' + +describe('Validated', () => { + describe('constructor functions', () => { + test('valid', () => { + const validated = valid({ some: 'object ' }) + expect(validated).toHaveProperty('valid', true) + expect(validated).toHaveProperty('value', { some: 'object ' }) + }) + + test('invalid', () => { + const validated = invalid(['reasons']) + expect(validated).toHaveProperty('valid', false) + expect(validated).toHaveProperty('reasons', ['reasons']) + }) + }) + + describe('map', () => { + it('should map value of valid', () => { + expect(valid(5).map((value) => value * 2)).toEqual( + expect.objectContaining({ + valid: true, + value: 10 + }) + ) + }) + + it('should do nothing for invalid', () => { + expect( + invalid(['hello']).map((value) => value * 2) + ).toEqual( + expect.objectContaining({ + valid: false, + reasons: ['hello'] + }) + ) + }) + }) + + describe('mapError', () => { + it('should do nothing for valid', () => { + expect(valid(5).mapError((reasons) => reasons.concat('another reason'))).toEqual( + expect.objectContaining({ + valid: true, + value: 5 + }) + ) + }) + + it('should map reasons of invalid', () => { + expect( + invalid(['hello']).mapError((reasons) => reasons.concat('another reason')) + ).toEqual( + expect.objectContaining({ + valid: false, + reasons: ['hello', 'another reason'] + }) + ) + }) + }) + + describe('flatMap', () => { + it('should map value of valid when returning valid', () => { + expect(valid(5).flatMap((value) => valid(value * 2))).toEqual( + expect.objectContaining({ + valid: true, + value: 10 + }) + ) + }) + + it('should map value of valid when returning invalid', () => { + expect(valid(5).flatMap((value) => invalid([`no ${value}`]))).toEqual( + expect.objectContaining({ + valid: false, + reasons: ['no 5'] + }) + ) + }) + + it('should do nothing for invalid', () => { + expect( + invalid(['hello']).flatMap((value) => valid(value * 2)) + ).toEqual( + expect.objectContaining({ + valid: false, + reasons: ['hello'] + }) + ) + }) + }) + + describe('awaitValue', () => { + it('should await the value of a valid', async () => { + expect(await valid(Promise.resolve(5)).awaitValue()).toEqual( + expect.objectContaining({ + valid: true, + value: 5 + }) + ) + }) + + it('should do nothing for invalid', async () => { + expect(await invalid(['hello']).awaitValue()).toEqual( + expect.objectContaining({ + valid: false, + reasons: ['hello'] + }) + ) + }) + }) + + describe('unwrap', () => { + it('should return the value of a valid', () => { + expect(valid(5).unwrap()).toBe(5) + }) + + it('should throw message and reasons for invalid', () => { + expect(() => invalid(['hello', 'there']).unwrap('invalid!')).toThrowError( + expect.objectContaining({ + message: 'invalid!', + details: 'hello\n\nthere' + }) + ) + }) + }) + + describe('reduceValidated', () => { + it('should return valid with array if all are valid', () => { + expect(reduceValidated([valid(1), valid(2), valid(3)])).toEqual( + expect.objectContaining({ + valid: true, + value: [1, 2, 3] + }) + ) + }) + + it('should return invalid concatenating reasons if any are invalid', () => { + expect( + reduceValidated([ + valid(1), + invalid(['hello', 'there']), + valid(2), + invalid(['general', 'kenobi']), + valid(3) + ]) + ).toEqual( + expect.objectContaining({ + valid: false, + reasons: ['hello', 'there', 'general', 'kenobi'] + }) + ) + }) + }) +}) diff --git a/lib/validated/tsconfig.json b/lib/validated/tsconfig.json index de4070b0a..7399e5867 100644 --- a/lib/validated/tsconfig.json +++ b/lib/validated/tsconfig.json @@ -1,5 +1,6 @@ { "extends": "../../tsconfig.settings.json", + "include": ["src/**/*"], "compilerOptions": { "outDir": "lib", "rootDir": "src" From a35d06d79eec871da02172f9589ddc0fe5da78c9 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 13:05:46 +0000 Subject: [PATCH 084/321] chore: add validated to release please config --- release-please-config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/release-please-config.json b/release-please-config.json index df950488a..66a24b65d 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -14,6 +14,7 @@ "plugins/package-json-hook": {}, "lib/state": {}, "lib/types": {}, + "lib/validated": {}, "lib/vault": {}, "lib/wait-for-ok": {}, "orb": { From 8328b9634ea33d45ad2865b5c1711acaca67f7d1 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 14:34:18 +0000 Subject: [PATCH 085/321] docs: more specific rust docs link Co-authored-by: Ivo Murrell --- lib/validated/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/validated/README.md b/lib/validated/README.md index 325b4aa8e..327c439fd 100644 --- a/lib/validated/README.md +++ b/lib/validated/README.md @@ -12,7 +12,7 @@ We _could_ still use exceptions/rejections for this, along with `Promise.allSett Instead, we model these errors using an explicit return value, `Validated`. This type is a union of `Valid` which represents a correct value, and `Invalid` which represents a problem with a list of `string` reasons. By making this an explicit type, we clearly mark all the functions that can return errors we may want to collate, and make it impossible to use the values without deciding what to do with the errors. -This pattern is modelled after Go's [error handling using multiple return values](https://go.dev/doc/tutorial/handle-errors), Rust's [`Result` type](https://doc.rust-lang.org/book/ch09-00-error-handling.html) and Haskell's [`Either a b` type](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Either.html). +This pattern is modelled after Go's [error handling using multiple return values](https://go.dev/doc/tutorial/handle-errors), Rust's [`Result` type](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html) and Haskell's [`Either a b` type](https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Either.html). ## Usage From 97cb9a88cb95fe6b9cf7f74ee80f0c1c3ef56708 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 14:34:50 +0000 Subject: [PATCH 086/321] docs: clearer map example comments Co-authored-by: Ivo Murrell --- lib/validated/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/validated/README.md b/lib/validated/README.md index 327c439fd..576046bbc 100644 --- a/lib/validated/README.md +++ b/lib/validated/README.md @@ -34,13 +34,13 @@ invalid([ ```typescript validated.map(value => { - // do something with value - return // something else. replaces the value with this return value if valid, does nothing if invalid + /* do something with value */ + // `return` something else. replaces the value with this return value if valid, does nothing if invalid }) validated.mapError(reasons => { - // do something with reasons - return // something else. replaces the reasons with this return value if invalid, does nothing if valid + /* do something with reasons */ + // `return` something else. replaces the reasons with this return value if invalid, does nothing if valid }) ``` From 6aecf3585aab155fe6f356997fd60bd5c34c38ef Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 17:08:02 +0000 Subject: [PATCH 087/321] feat: split schemas out into separate package --- core/cli/src/install.ts | 4 +- core/cli/src/plugin/options.ts | 4 +- core/cli/src/plugin/reduce-installations.ts | 2 +- core/create/package.json | 1 + core/create/src/bizOps.ts | 2 +- core/create/src/prompts/options.ts | 4 +- core/create/tsconfig.json | 3 + docs/developing-tool-kit.md | 4 +- lib/doppler/package.json | 1 + lib/doppler/src/index.ts | 2 +- lib/doppler/tsconfig.json | 3 + lib/options/package.json | 2 +- lib/options/src/index.ts | 10 +- lib/options/tsconfig.json | 2 +- lib/schemas/package.json | 19 ++++ lib/{types => schemas}/src/bizOps.ts | 0 lib/{types => schemas}/src/hooks.ts | 2 +- .../src}/hooks/package-json.ts | 0 lib/schemas/src/index.ts | 3 + lib/schemas/src/plugins.ts | 54 +++++++++++ .../schema => schemas/src}/plugins/babel.ts | 0 .../src}/plugins/circleci.ts | 0 .../schema => schemas/src}/plugins/cypress.ts | 0 .../schema => schemas/src}/plugins/doppler.ts | 0 .../src}/plugins/dotcom-tool-kit.ts | 0 .../schema => schemas/src}/plugins/eslint.ts | 0 .../schema => schemas/src}/plugins/heroku.ts | 2 +- .../schema => schemas/src}/plugins/jest.ts | 0 .../src}/plugins/lint-staged-npm.ts | 0 .../schema => schemas/src}/plugins/mocha.ts | 0 .../schema => schemas/src}/plugins/n-test.ts | 0 .../src}/plugins/next-router.ts | 0 .../schema => schemas/src}/plugins/node.ts | 0 .../schema => schemas/src}/plugins/nodemon.ts | 0 .../schema => schemas/src}/plugins/pa11y.ts | 0 .../src}/plugins/prettier.ts | 0 .../src}/plugins/serverless.ts | 2 +- .../src}/plugins/typescript.ts | 0 .../src}/plugins/upload-assets-to-s3.ts | 0 .../schema => schemas/src}/plugins/vault.ts | 0 .../schema => schemas/src}/plugins/webpack.ts | 0 lib/schemas/src/prompts.ts | 33 +++++++ lib/schemas/tsconfig.json | 7 ++ lib/types/package.json | 3 +- lib/types/src/index.ts | 2 +- lib/types/src/plugins.ts | 86 ------------------ lib/types/tsconfig.json | 3 + lib/vault/package.json | 1 + lib/vault/src/index.ts | 2 +- lib/vault/tsconfig.json | 3 + package-lock.json | 91 ++++++++++++++++++- plugins/babel/package.json | 1 + plugins/babel/src/run-babel.ts | 2 +- plugins/babel/src/tasks/development.ts | 2 +- plugins/babel/src/tasks/production.ts | 2 +- plugins/babel/tsconfig.json | 3 + plugins/cypress/package.json | 3 +- plugins/cypress/src/tasks/ci.ts | 2 +- plugins/cypress/src/tasks/local.ts | 2 +- plugins/cypress/tsconfig.json | 3 + plugins/eslint/package.json | 1 + plugins/eslint/src/tasks/eslint.ts | 2 +- plugins/eslint/tsconfig.json | 3 + plugins/heroku/package.json | 1 + plugins/heroku/src/tasks/production.ts | 2 +- plugins/heroku/src/tasks/review.ts | 2 +- plugins/heroku/src/tasks/staging.ts | 2 +- plugins/heroku/tsconfig.json | 3 + plugins/jest/package.json | 5 +- plugins/jest/src/run-jest.ts | 2 +- plugins/jest/src/tasks/ci.ts | 2 +- plugins/jest/src/tasks/local.ts | 2 +- plugins/jest/tsconfig.json | 7 +- plugins/mocha/package.json | 1 + plugins/mocha/src/tasks/mocha.ts | 2 +- plugins/mocha/tsconfig.json | 3 + plugins/n-test/package.json | 1 + plugins/n-test/src/tasks/n-test.ts | 2 +- plugins/n-test/tsconfig.json | 3 + plugins/next-router/package.json | 3 + plugins/next-router/src/tasks/next-router.ts | 2 +- plugins/next-router/tsconfig.json | 3 + plugins/node/package.json | 3 + plugins/node/src/tasks/node.ts | 2 +- plugins/node/tsconfig.json | 3 + plugins/nodemon/package.json | 5 +- plugins/nodemon/src/tasks/nodemon.ts | 2 +- plugins/nodemon/tsconfig.json | 3 + plugins/pa11y/src/tasks/pa11y.ts | 2 +- plugins/pa11y/tsconfig.json | 3 + plugins/package-json-hook/package.json | 1 + .../src/package-json-helper.ts | 2 +- plugins/package-json-hook/test/index.test.ts | 2 +- plugins/package-json-hook/tsconfig.json | 3 + plugins/prettier/src/tasks/prettier.ts | 2 +- plugins/prettier/tsconfig.json | 3 + plugins/serverless/package.json | 3 + plugins/serverless/src/tasks/deploy.ts | 2 +- plugins/serverless/src/tasks/provision.ts | 2 +- plugins/serverless/src/tasks/run.ts | 2 +- plugins/serverless/src/tasks/teardown.ts | 2 +- plugins/serverless/tsconfig.json | 3 + plugins/typescript/package.json | 1 + plugins/typescript/src/tasks/typescript.ts | 2 +- plugins/typescript/tsconfig.json | 3 + plugins/upload-assets-to-s3/package.json | 1 + .../src/tasks/upload-assets-to-s3.ts | 2 +- .../test/tasks/upload-assets-to-s3.test.ts | 2 +- plugins/upload-assets-to-s3/tsconfig.json | 3 + plugins/webpack/package.json | 5 +- plugins/webpack/src/run-webpack.ts | 2 +- plugins/webpack/src/tasks/development.ts | 2 +- plugins/webpack/src/tasks/production.ts | 2 +- plugins/webpack/src/tasks/watch.ts | 2 +- plugins/webpack/tsconfig.json | 3 + tsconfig.json | 3 + 116 files changed, 360 insertions(+), 154 deletions(-) create mode 100644 lib/schemas/package.json rename lib/{types => schemas}/src/bizOps.ts (100%) rename lib/{types => schemas}/src/hooks.ts (83%) rename lib/{types/src/schema => schemas/src}/hooks/package-json.ts (100%) create mode 100644 lib/schemas/src/index.ts create mode 100644 lib/schemas/src/plugins.ts rename lib/{types/src/schema => schemas/src}/plugins/babel.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/circleci.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/cypress.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/doppler.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/dotcom-tool-kit.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/eslint.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/heroku.ts (98%) rename lib/{types/src/schema => schemas/src}/plugins/jest.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/lint-staged-npm.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/mocha.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/n-test.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/next-router.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/node.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/nodemon.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/pa11y.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/prettier.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/serverless.ts (96%) rename lib/{types/src/schema => schemas/src}/plugins/typescript.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/upload-assets-to-s3.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/vault.ts (100%) rename lib/{types/src/schema => schemas/src}/plugins/webpack.ts (100%) create mode 100644 lib/schemas/src/prompts.ts create mode 100644 lib/schemas/tsconfig.json delete mode 100644 lib/types/src/plugins.ts diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 4fe1be87e..73560acbb 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -9,7 +9,7 @@ import { Hook, HookClass, ValidConfig } from '@dotcom-tool-kit/types' import { Validated, invalid, reduceValidated, valid } from '@dotcom-tool-kit/validated' import { reducePluginHookInstallations } from './plugin/reduce-installations' import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/types/src/conflict' -import { Options as HookSchemaOptions, HookSchemas } from '@dotcom-tool-kit/types/lib/hooks' +import { HookOptions, HookSchemas } from '@dotcom-tool-kit/schemas' import { formatUninstalledHooks } from './messages' import { importEntryPoint } from './plugin/entry-point' import { runInit } from './init' @@ -70,7 +70,7 @@ export const loadHookInstallations = async ( return installationsWithoutConflicts.map((installations) => { return installations.map(({ hookConstructor, forHook, options }) => { - const schema = HookSchemas[forHook as keyof HookSchemaOptions] + const schema = HookSchemas[forHook as keyof HookOptions] const parsedOptions = schema ? schema.parse(options) : {} return new hookConstructor(logger, forHook, parsedOptions) }) diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index 02ee625dc..3fd87a944 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -1,6 +1,6 @@ import { ValidPluginsConfig } from '@dotcom-tool-kit/types' import { InvalidOption } from '../messages' -import { Options as SchemaOptions, Schemas } from '@dotcom-tool-kit/types/lib/plugins' +import { SchemaOptions, PluginSchemas } from '@dotcom-tool-kit/schemas' import { isConflict } from '@dotcom-tool-kit/types/src/conflict' import type { Logger } from 'winston' @@ -14,7 +14,7 @@ export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig continue } - const pluginSchema = Schemas[pluginId] + const pluginSchema = PluginSchemas[pluginId] if (!pluginSchema) { logger.silly(`skipping validation of ${pluginId} plugin as no schema can be found`) continue diff --git a/core/cli/src/plugin/reduce-installations.ts b/core/cli/src/plugin/reduce-installations.ts index 7042fd769..67d0339ae 100644 --- a/core/cli/src/plugin/reduce-installations.ts +++ b/core/cli/src/plugin/reduce-installations.ts @@ -2,7 +2,7 @@ import { Logger } from 'winston' import { HookClass, HookInstallation, Plugin, ValidConfig } from '@dotcom-tool-kit/types' import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' import { groupBy } from 'lodash' -import { HookSchemas, Options as HookOptions } from '@dotcom-tool-kit/types/src/hooks' +import { HookSchemas, HookOptions } from '@dotcom-tool-kit/schemas' // this function recursively collects all the hook installation requests from all plugins, // and merges them into a single, flat array of HookInstallation objects and/or Conflicts. diff --git a/core/create/package.json b/core/create/package.json index 00f0ebae8..897fc2cfc 100644 --- a/core/create/package.json +++ b/core/create/package.json @@ -16,6 +16,7 @@ "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/schemas": "^1.0.0", "@dotcom-tool-kit/types": "^3.6.0", "@octokit/rest": "^19.0.5", "@quarterto/parse-makefile-rules": "^1.1.0", diff --git a/core/create/src/bizOps.ts b/core/create/src/bizOps.ts index 1e325e6a0..9075d2672 100644 --- a/core/create/src/bizOps.ts +++ b/core/create/src/bizOps.ts @@ -1,6 +1,6 @@ import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { rootLogger as winstonLogger } from '@dotcom-tool-kit/logger' -import { BizOpsData, BizOpsSystem } from '@dotcom-tool-kit/types/lib/bizOps' +import { BizOpsData, BizOpsSystem } from '@dotcom-tool-kit/schemas/lib/bizOps' import fetch from 'node-fetch' let bizOpsApiKey: string diff --git a/core/create/src/prompts/options.ts b/core/create/src/prompts/options.ts index be4c83b0c..99367508f 100644 --- a/core/create/src/prompts/options.ts +++ b/core/create/src/prompts/options.ts @@ -1,6 +1,6 @@ import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' import type { RCFile, RawConfig } from '@dotcom-tool-kit/types' -import type { PromptGenerators } from '@dotcom-tool-kit/types/src/plugins' +import type { PromptGenerators } from '@dotcom-tool-kit/schemas' import { promises as fs } from 'fs' import YAML from 'yaml' import type Logger from 'komatsu' @@ -207,7 +207,7 @@ export default async ({ // TODO allow different schemas for tasks within a plugin const { Schema, generators: SchemaGenerators } = // eslint-disable-next-line @typescript-eslint/no-var-requires - require(`@dotcom-tool-kit/types/lib/schema/plugins/${pluginName}`) + require(`@dotcom-tool-kit/schemas/lib/plugins/${pluginName}`) options = Schema generators = SchemaGenerators } catch (err) { diff --git a/core/create/tsconfig.json b/core/create/tsconfig.json index 275fc45f7..695961edc 100644 --- a/core/create/tsconfig.json +++ b/core/create/tsconfig.json @@ -14,6 +14,9 @@ { "path": "../../lib/types" }, + { + "path": "../../lib/schemas" + }, { "path": "../cli" } diff --git a/docs/developing-tool-kit.md b/docs/developing-tool-kit.md index 2ba3a0ac7..1b6b90d8c 100644 --- a/docs/developing-tool-kit.md +++ b/docs/developing-tool-kit.md @@ -94,7 +94,7 @@ This lets different plugins define the same abstractly labelled hooks with diffe #### Defining options -Plugins can define options that a user can configure in their repo's `.toolkitrc.yml`. We use the [`zod` library](https://zod.dev) to specify the schema, which allows us to define what we expect the options to look like and use this specification to validate the options we receive as well as generate TypeScript types for them. Options are defined in the `@dotcom-tool-kit/types` package, in the `schema` files. Create a file in [`src/schema`](../lib/types/src/schema/plugins) for your plugin, which should export a `NameOfPluginSchema` object (that should also be exported as `Schema`), and a `NameOfPluginOptions` type that uses the `SchemaOutput` generic type. +Plugins can define options that a user can configure in their repo's `.toolkitrc.yml`. We use the [`zod` library](https://zod.dev) to specify the schema, which allows us to define what we expect the options to look like and use this specification to validate the options we receive as well as generate TypeScript types for them. Options are defined in the `@dotcom-tool-kit/types` package, in the `schema` files. Create a file in [`src/schema`](../lib/schema/lib/plugins) for your plugin, which should export a `NameOfPluginSchema` object (that should also be exported as `Schema`), and a `NameOfPluginOptions` type that uses the `SchemaOutput` generic type. ```typescript import { z } from 'zod' @@ -136,7 +136,7 @@ To avoid boilerplate for tasks (the most common use case for options), when defi ```typescript import { Task } from '@dotcom-tool-kit/types' -import { ESLintOptions, ESLintSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/eslint' +import { ESLintOptions, ESLintSchema } from '@dotcom-tool-kit/schemas/lib/plugins/eslint' export default class Eslint extends Task { static description = '' diff --git a/lib/doppler/package.json b/lib/doppler/package.json index ca24d53fd..e3c781833 100644 --- a/lib/doppler/package.json +++ b/lib/doppler/package.json @@ -32,6 +32,7 @@ "extends": "../../package.json" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "spawk": "^1.8.1", "winston": "^3.5.1" }, diff --git a/lib/doppler/src/index.ts b/lib/doppler/src/index.ts index 03d0d11ba..d5855b39d 100644 --- a/lib/doppler/src/index.ts +++ b/lib/doppler/src/index.ts @@ -7,7 +7,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { styles, waitOnExit } from '@dotcom-tool-kit/logger' import { getOptions } from '@dotcom-tool-kit/options' import * as Vault from '@dotcom-tool-kit/vault' -import type { DopplerOptions as ConfiguredDopplerOptions } from '@dotcom-tool-kit/types/lib/schema/plugins/doppler' +import type { DopplerOptions as ConfiguredDopplerOptions } from '@dotcom-tool-kit/schemas/lib/plugins/doppler' export type Environment = 'prod' | 'ci' | 'dev' diff --git a/lib/doppler/tsconfig.json b/lib/doppler/tsconfig.json index 244163209..aaa177477 100644 --- a/lib/doppler/tsconfig.json +++ b/lib/doppler/tsconfig.json @@ -15,6 +15,9 @@ }, { "path": "../vault" + }, + { + "path": "../schemas" } ], "compilerOptions": { diff --git a/lib/options/package.json b/lib/options/package.json index 91233f3a9..5b293845f 100644 --- a/lib/options/package.json +++ b/lib/options/package.json @@ -10,7 +10,7 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/schemas": "^1.0.0", "tslib": "^2.3.1" }, "repository": { diff --git a/lib/options/src/index.ts b/lib/options/src/index.ts index 8495f29a5..5aa2f8f38 100644 --- a/lib/options/src/index.ts +++ b/lib/options/src/index.ts @@ -1,11 +1,11 @@ -import type { Options } from '@dotcom-tool-kit/types/src/plugins' +import type { SchemaOptions } from '@dotcom-tool-kit/schemas' -const options: Partial = {} +const options: Partial = {} -export type OptionKey = keyof Options +export type OptionKey = keyof SchemaOptions -export const getOptions = (plugin: T): Options[T] | undefined => options[plugin] +export const getOptions = (plugin: T): SchemaOptions[T] | undefined => options[plugin] -export const setOptions = (plugin: T, opts: Options[T]): void => { +export const setOptions = (plugin: T, opts: SchemaOptions[T]): void => { options[plugin] = opts } diff --git a/lib/options/tsconfig.json b/lib/options/tsconfig.json index d4577cf4e..3da3621a6 100644 --- a/lib/options/tsconfig.json +++ b/lib/options/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../types" + "path": "../schemas" } ], "include": ["src/**/*"] diff --git a/lib/schemas/package.json b/lib/schemas/package.json new file mode 100644 index 000000000..271e572a8 --- /dev/null +++ b/lib/schemas/package.json @@ -0,0 +1,19 @@ +{ + "name": "@dotcom-tool-kit/schemas", + "version": "1.0.0", + "description": "", + "main": "lib", + "devDependencies": { + "prompts": "^2.4.2", + "winston": "^3.11.0" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "zod": "^3.20.6" + } +} diff --git a/lib/types/src/bizOps.ts b/lib/schemas/src/bizOps.ts similarity index 100% rename from lib/types/src/bizOps.ts rename to lib/schemas/src/bizOps.ts diff --git a/lib/types/src/hooks.ts b/lib/schemas/src/hooks.ts similarity index 83% rename from lib/types/src/hooks.ts rename to lib/schemas/src/hooks.ts index 678748fb0..c6c8a4820 100644 --- a/lib/types/src/hooks.ts +++ b/lib/schemas/src/hooks.ts @@ -1,6 +1,6 @@ import { z } from 'zod' -import { PackageJsonSchema } from './schema/hooks/package-json' +import { PackageJsonSchema } from './hooks/package-json' export const HookSchemas = { PackageJson: PackageJsonSchema diff --git a/lib/types/src/schema/hooks/package-json.ts b/lib/schemas/src/hooks/package-json.ts similarity index 100% rename from lib/types/src/schema/hooks/package-json.ts rename to lib/schemas/src/hooks/package-json.ts diff --git a/lib/schemas/src/index.ts b/lib/schemas/src/index.ts new file mode 100644 index 000000000..2dbfa5317 --- /dev/null +++ b/lib/schemas/src/index.ts @@ -0,0 +1,3 @@ +export { Options as SchemaOptions, Schemas as PluginSchemas } from './plugins' +export { Options as HookOptions, HookSchemas } from './hooks' +export * from './prompts' diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts new file mode 100644 index 000000000..4bc714ddd --- /dev/null +++ b/lib/schemas/src/plugins.ts @@ -0,0 +1,54 @@ +import type { z } from 'zod' + +import { BabelSchema } from './plugins/babel' +import { CircleCISchema } from './plugins/circleci' +import { CypressSchema } from './plugins/cypress' +import { DopplerSchema } from './plugins/doppler' +import { RootSchema } from './plugins/dotcom-tool-kit' +import { ESLintSchema } from './plugins/eslint' +import { HerokuSchema } from './plugins/heroku' +import { LintStagedNpmSchema } from './plugins/lint-staged-npm' +import { JestSchema } from './plugins/jest' +import { MochaSchema } from './plugins/mocha' +import { SmokeTestSchema } from './plugins/n-test' +import { NextRouterSchema } from './plugins/next-router' +import { NodeSchema } from './plugins/node' +import { NodemonSchema } from './plugins/nodemon' +import { Pa11ySchema } from './plugins/pa11y' +import { PrettierSchema } from './plugins/prettier' +import { ServerlessSchema } from './plugins/serverless' +import { TypeScriptSchema } from './plugins/typescript' +import { UploadAssetsToS3Schema } from './plugins/upload-assets-to-s3' +import { VaultSchema } from './plugins/vault' +import { WebpackSchema } from './plugins/webpack' + +export const Schemas = { + 'app root': RootSchema, + '@dotcom-tool-kit/babel': BabelSchema, + '@dotcom-tool-kit/circleci': CircleCISchema, + '@dotcom-tool-kit/cypress': CypressSchema, + '@dotcom-tool-kit/doppler': DopplerSchema, + '@dotcom-tool-kit/eslint': ESLintSchema, + '@dotcom-tool-kit/heroku': HerokuSchema, + '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, + '@dotcom-tool-kit/jest': JestSchema, + '@dotcom-tool-kit/mocha': MochaSchema, + '@dotcom-tool-kit/n-test': SmokeTestSchema, + '@dotcom-tool-kit/next-router': NextRouterSchema, + '@dotcom-tool-kit/node': NodeSchema, + '@dotcom-tool-kit/nodemon': NodemonSchema, + '@dotcom-tool-kit/pa11y': Pa11ySchema, + '@dotcom-tool-kit/prettier': PrettierSchema, + '@dotcom-tool-kit/serverless': ServerlessSchema, + '@dotcom-tool-kit/typescript': TypeScriptSchema, + '@dotcom-tool-kit/upload-assets-to-s3': UploadAssetsToS3Schema, + '@dotcom-tool-kit/vault': VaultSchema, + '@dotcom-tool-kit/webpack': WebpackSchema +} + +// Gives the TypeScript type represented by each Schema +export type Options = { + [plugin in keyof typeof Schemas]: typeof Schemas[plugin] extends z.ZodTypeAny + ? z.infer + : never +} diff --git a/lib/types/src/schema/plugins/babel.ts b/lib/schemas/src/plugins/babel.ts similarity index 100% rename from lib/types/src/schema/plugins/babel.ts rename to lib/schemas/src/plugins/babel.ts diff --git a/lib/types/src/schema/plugins/circleci.ts b/lib/schemas/src/plugins/circleci.ts similarity index 100% rename from lib/types/src/schema/plugins/circleci.ts rename to lib/schemas/src/plugins/circleci.ts diff --git a/lib/types/src/schema/plugins/cypress.ts b/lib/schemas/src/plugins/cypress.ts similarity index 100% rename from lib/types/src/schema/plugins/cypress.ts rename to lib/schemas/src/plugins/cypress.ts diff --git a/lib/types/src/schema/plugins/doppler.ts b/lib/schemas/src/plugins/doppler.ts similarity index 100% rename from lib/types/src/schema/plugins/doppler.ts rename to lib/schemas/src/plugins/doppler.ts diff --git a/lib/types/src/schema/plugins/dotcom-tool-kit.ts b/lib/schemas/src/plugins/dotcom-tool-kit.ts similarity index 100% rename from lib/types/src/schema/plugins/dotcom-tool-kit.ts rename to lib/schemas/src/plugins/dotcom-tool-kit.ts diff --git a/lib/types/src/schema/plugins/eslint.ts b/lib/schemas/src/plugins/eslint.ts similarity index 100% rename from lib/types/src/schema/plugins/eslint.ts rename to lib/schemas/src/plugins/eslint.ts diff --git a/lib/types/src/schema/plugins/heroku.ts b/lib/schemas/src/plugins/heroku.ts similarity index 98% rename from lib/types/src/schema/plugins/heroku.ts rename to lib/schemas/src/plugins/heroku.ts index 9912a6689..57783457d 100644 --- a/lib/types/src/schema/plugins/heroku.ts +++ b/lib/schemas/src/plugins/heroku.ts @@ -1,4 +1,4 @@ -import { SchemaPromptGenerator, PromptGenerators } from '../../plugins' +import { SchemaPromptGenerator, PromptGenerators } from '../prompts' import { waitOnExit } from '@dotcom-tool-kit/logger' diff --git a/lib/types/src/schema/plugins/jest.ts b/lib/schemas/src/plugins/jest.ts similarity index 100% rename from lib/types/src/schema/plugins/jest.ts rename to lib/schemas/src/plugins/jest.ts diff --git a/lib/types/src/schema/plugins/lint-staged-npm.ts b/lib/schemas/src/plugins/lint-staged-npm.ts similarity index 100% rename from lib/types/src/schema/plugins/lint-staged-npm.ts rename to lib/schemas/src/plugins/lint-staged-npm.ts diff --git a/lib/types/src/schema/plugins/mocha.ts b/lib/schemas/src/plugins/mocha.ts similarity index 100% rename from lib/types/src/schema/plugins/mocha.ts rename to lib/schemas/src/plugins/mocha.ts diff --git a/lib/types/src/schema/plugins/n-test.ts b/lib/schemas/src/plugins/n-test.ts similarity index 100% rename from lib/types/src/schema/plugins/n-test.ts rename to lib/schemas/src/plugins/n-test.ts diff --git a/lib/types/src/schema/plugins/next-router.ts b/lib/schemas/src/plugins/next-router.ts similarity index 100% rename from lib/types/src/schema/plugins/next-router.ts rename to lib/schemas/src/plugins/next-router.ts diff --git a/lib/types/src/schema/plugins/node.ts b/lib/schemas/src/plugins/node.ts similarity index 100% rename from lib/types/src/schema/plugins/node.ts rename to lib/schemas/src/plugins/node.ts diff --git a/lib/types/src/schema/plugins/nodemon.ts b/lib/schemas/src/plugins/nodemon.ts similarity index 100% rename from lib/types/src/schema/plugins/nodemon.ts rename to lib/schemas/src/plugins/nodemon.ts diff --git a/lib/types/src/schema/plugins/pa11y.ts b/lib/schemas/src/plugins/pa11y.ts similarity index 100% rename from lib/types/src/schema/plugins/pa11y.ts rename to lib/schemas/src/plugins/pa11y.ts diff --git a/lib/types/src/schema/plugins/prettier.ts b/lib/schemas/src/plugins/prettier.ts similarity index 100% rename from lib/types/src/schema/plugins/prettier.ts rename to lib/schemas/src/plugins/prettier.ts diff --git a/lib/types/src/schema/plugins/serverless.ts b/lib/schemas/src/plugins/serverless.ts similarity index 96% rename from lib/types/src/schema/plugins/serverless.ts rename to lib/schemas/src/plugins/serverless.ts index 5086d2165..310c51e47 100644 --- a/lib/types/src/schema/plugins/serverless.ts +++ b/lib/schemas/src/plugins/serverless.ts @@ -1,4 +1,4 @@ -import { PromptGenerators } from '../schema' +import { PromptGenerators } from '../prompts' import { z } from 'zod' export const ServerlessSchema = z.object({ diff --git a/lib/types/src/schema/plugins/typescript.ts b/lib/schemas/src/plugins/typescript.ts similarity index 100% rename from lib/types/src/schema/plugins/typescript.ts rename to lib/schemas/src/plugins/typescript.ts diff --git a/lib/types/src/schema/plugins/upload-assets-to-s3.ts b/lib/schemas/src/plugins/upload-assets-to-s3.ts similarity index 100% rename from lib/types/src/schema/plugins/upload-assets-to-s3.ts rename to lib/schemas/src/plugins/upload-assets-to-s3.ts diff --git a/lib/types/src/schema/plugins/vault.ts b/lib/schemas/src/plugins/vault.ts similarity index 100% rename from lib/types/src/schema/plugins/vault.ts rename to lib/schemas/src/plugins/vault.ts diff --git a/lib/types/src/schema/plugins/webpack.ts b/lib/schemas/src/plugins/webpack.ts similarity index 100% rename from lib/types/src/schema/plugins/webpack.ts rename to lib/schemas/src/plugins/webpack.ts diff --git a/lib/schemas/src/prompts.ts b/lib/schemas/src/prompts.ts new file mode 100644 index 000000000..50a339b08 --- /dev/null +++ b/lib/schemas/src/prompts.ts @@ -0,0 +1,33 @@ +import type prompts from 'prompts' +import type { Logger } from 'winston' +import type { z } from 'zod' + +import type { BizOpsSystem } from './bizOps' + +/** + * A function that should use the `prompt` parameter passed to build a more + * complex option structure, like a nested object, from user input. Returning + * an undefined value will cause the program to fall back to the default prompt + * interface. + * @param onCancel - pass this to `prompt`'s options so that a user + * interrupting the prompt can be handled properly + */ +export type SchemaPromptGenerator = ( + logger: Logger, + prompt: typeof prompts, + onCancel: () => void, + // HACK:20231209:IM add bizOpsSystem as optional parameter to maintain + // backwards compatibility + bizOpsSystem?: BizOpsSystem +) => Promise +// This type defines an interface you can use to export prompt generators. The +// `T` type parameter should be the type of your `Schema` object, and it will +// be mapped into a partial object of `SchemaPromptGenerator` functions with +// all their return types set to the output type of each option schema. +export type PromptGenerators = T extends z.ZodObject + ? { + [option in keyof Shape as Shape[option] extends z.ZodType + ? option + : never]?: Shape[option] extends z.ZodType ? SchemaPromptGenerator> : never + } + : never diff --git a/lib/schemas/tsconfig.json b/lib/schemas/tsconfig.json new file mode 100644 index 000000000..72bbe0165 --- /dev/null +++ b/lib/schemas/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.settings.json", + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + } +} diff --git a/lib/types/package.json b/lib/types/package.json index 0c443284c..c5c2d7667 100644 --- a/lib/types/package.json +++ b/lib/types/package.json @@ -28,9 +28,10 @@ "@dotcom-tool-kit/validated": "^1.0.0", "semver": "^7.3.7", "tslib": "^2.3.1", - "zod": "^3.20.2" + "zod": "^3.20.6" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/prompts": "^2.0.14", "@types/semver": "^7.3.9", diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index f181a6dfb..36418f4b0 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -1,6 +1,6 @@ import type { Conflict } from './conflict' import type { Validated } from '@dotcom-tool-kit/validated' -import type { Options as SchemaOptions } from './plugins' +import type { SchemaOptions } from '@dotcom-tool-kit/schemas' export * from '@dotcom-tool-kit/validated' export * from './base' diff --git a/lib/types/src/plugins.ts b/lib/types/src/plugins.ts deleted file mode 100644 index a68ff5cdb..000000000 --- a/lib/types/src/plugins.ts +++ /dev/null @@ -1,86 +0,0 @@ -import type prompts from 'prompts' -import type { Logger } from 'winston' -import { z } from 'zod' - -import { BizOpsSystem } from './bizOps' - -/** - * A function that should use the `prompt` parameter passed to build a more - * complex option structure, like a nested object, from user input. Returning - * an undefined value will cause the program to fall back to the default prompt - * interface. - * @param onCancel - pass this to `prompt`'s options so that a user - * interrupting the prompt can be handled properly - */ -export type SchemaPromptGenerator = ( - logger: Logger, - prompt: typeof prompts, - onCancel: () => void, - // HACK:20231209:IM add bizOpsSystem as optional parameter to maintain - // backwards compatibility - bizOpsSystem?: BizOpsSystem -) => Promise -// This type defines an interface you can use to export prompt generators. The -// `T` type parameter should be the type of your `Schema` object, and it will -// be mapped into a partial object of `SchemaPromptGenerator` functions with -// all their return types set to the output type of each option schema. -export type PromptGenerators = T extends z.ZodObject - ? { - [option in keyof Shape as Shape[option] extends z.ZodType - ? option - : never]?: Shape[option] extends z.ZodType ? SchemaPromptGenerator> : never - } - : never - -import { BabelSchema } from './schema/plugins/babel' -import { CircleCISchema } from './schema/plugins/circleci' -import { CypressSchema } from './schema/plugins/cypress' -import { DopplerSchema } from './schema/plugins/doppler' -import { RootSchema } from './schema/plugins/dotcom-tool-kit' -import { ESLintSchema } from './schema/plugins/eslint' -import { HerokuSchema } from './schema/plugins/heroku' -import { LintStagedNpmSchema } from './schema/plugins/lint-staged-npm' -import { JestSchema } from './schema/plugins/jest' -import { MochaSchema } from './schema/plugins/mocha' -import { SmokeTestSchema } from './schema/plugins/n-test' -import { NextRouterSchema } from './schema/plugins/next-router' -import { NodeSchema } from './schema/plugins/node' -import { NodemonSchema } from './schema/plugins/nodemon' -import { Pa11ySchema } from './schema/plugins/pa11y' -import { PrettierSchema } from './schema/plugins/prettier' -import { ServerlessSchema } from './schema/plugins/serverless' -import { TypeScriptSchema } from './schema/plugins/typescript' -import { UploadAssetsToS3Schema } from './schema/plugins/upload-assets-to-s3' -import { VaultSchema } from './schema/plugins/vault' -import { WebpackSchema } from './schema/plugins/webpack' - -export const Schemas = { - 'app root': RootSchema, - '@dotcom-tool-kit/babel': BabelSchema, - '@dotcom-tool-kit/circleci': CircleCISchema, - '@dotcom-tool-kit/cypress': CypressSchema, - '@dotcom-tool-kit/doppler': DopplerSchema, - '@dotcom-tool-kit/eslint': ESLintSchema, - '@dotcom-tool-kit/heroku': HerokuSchema, - '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, - '@dotcom-tool-kit/jest': JestSchema, - '@dotcom-tool-kit/mocha': MochaSchema, - '@dotcom-tool-kit/n-test': SmokeTestSchema, - '@dotcom-tool-kit/next-router': NextRouterSchema, - '@dotcom-tool-kit/node': NodeSchema, - '@dotcom-tool-kit/nodemon': NodemonSchema, - '@dotcom-tool-kit/pa11y': Pa11ySchema, - '@dotcom-tool-kit/prettier': PrettierSchema, - '@dotcom-tool-kit/serverless': ServerlessSchema, - '@dotcom-tool-kit/typescript': TypeScriptSchema, - '@dotcom-tool-kit/upload-assets-to-s3': UploadAssetsToS3Schema, - '@dotcom-tool-kit/vault': VaultSchema, - '@dotcom-tool-kit/webpack': WebpackSchema -} - -// Gives the TypeScript type represented by each Schema -export type Options = { - [plugin in keyof typeof Schemas]: typeof Schemas[plugin] extends z.ZodTypeAny - ? z.infer - : never -} diff --git a/lib/types/tsconfig.json b/lib/types/tsconfig.json index 547a1f2d1..4c2c21267 100644 --- a/lib/types/tsconfig.json +++ b/lib/types/tsconfig.json @@ -9,6 +9,9 @@ }, { "path": "../validated" + }, + { + "path": "../schemas" } ], "compilerOptions": { diff --git a/lib/vault/package.json b/lib/vault/package.json index 5f30a722a..afaff234f 100644 --- a/lib/vault/package.json +++ b/lib/vault/package.json @@ -35,6 +35,7 @@ "extends": "../../package.json" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@types/jest": "^27.0.2", "winston": "^3.5.1" }, diff --git a/lib/vault/src/index.ts b/lib/vault/src/index.ts index 1f5927672..25d425fb3 100644 --- a/lib/vault/src/index.ts +++ b/lib/vault/src/index.ts @@ -5,7 +5,7 @@ import os from 'os' import type { Logger } from 'winston' import { ToolKitError } from '@dotcom-tool-kit/error' import { getOptions } from '@dotcom-tool-kit/options' -import { VaultOptions } from '@dotcom-tool-kit/types/lib/schema/plugins/vault' +import { VaultOptions } from '@dotcom-tool-kit/schemas/lib/plugins/vault' const VAULT_ROLE_ID = process.env.VAULT_ROLE_ID const VAULT_SECRET_ID = process.env.VAULT_SECRET_ID diff --git a/lib/vault/tsconfig.json b/lib/vault/tsconfig.json index a8ef7bf3b..e2e650b6b 100644 --- a/lib/vault/tsconfig.json +++ b/lib/vault/tsconfig.json @@ -6,6 +6,9 @@ }, { "path": "../options" + }, + { + "path": "../schemas" } ], "compilerOptions": { diff --git a/package-lock.json b/package-lock.json index 4e91d6eb7..6c9bc9652 100644 --- a/package-lock.json +++ b/package-lock.json @@ -131,6 +131,7 @@ "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/schemas": "^1.0.0", "@dotcom-tool-kit/types": "^3.6.0", "@octokit/rest": "^19.0.5", "@quarterto/parse-makefile-rules": "^1.1.0", @@ -1113,6 +1114,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "spawk": "^1.8.1", "winston": "^3.5.1" }, @@ -1174,7 +1176,7 @@ "version": "3.2.0", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/schemas": "^1.0.0", "tslib": "^2.3.1" }, "engines": { @@ -1207,6 +1209,63 @@ "npm": "7.x || 8.x || 9.x || 10.x" } }, + "lib/schemas": { + "name": "@dotcom-tool-kit/schemas", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "zod": "^3.20.6" + }, + "devDependencies": { + "prompts": "^2.4.2", + "winston": "^3.11.0" + } + }, + "lib/schemas/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "lib/schemas/node_modules/winston": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz", + "integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==", + "dev": true, + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.7.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "lib/schemas/node_modules/winston-transport": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "dev": true, + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "lib/state": { "name": "@dotcom-tool-kit/state", "version": "3.3.0", @@ -1234,9 +1293,10 @@ "@dotcom-tool-kit/validated": "^1.0.0", "semver": "^7.3.7", "tslib": "^2.3.1", - "zod": "^3.20.2" + "zod": "^3.20.6" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/prompts": "^2.0.14", "@types/semver": "^7.3.9", @@ -1253,6 +1313,7 @@ "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "lib/validated": { + "name": "@dotcom-tool-kit/validated", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -1275,6 +1336,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@types/jest": "^27.0.2", "winston": "^3.5.1" }, @@ -6305,6 +6367,10 @@ "resolved": "plugins/prettier", "link": true }, + "node_modules/@dotcom-tool-kit/schemas": { + "resolved": "lib/schemas", + "link": true + }, "node_modules/@dotcom-tool-kit/serverless": { "resolved": "plugins/serverless", "link": true @@ -28830,6 +28896,7 @@ }, "devDependencies": { "@babel/preset-env": "^7.16.11", + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "winston": "^3.5.1" }, @@ -29119,6 +29186,7 @@ "dependencies": { "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/schemas": "^1.0.0", "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/types": "^3.6.0" }, @@ -29141,6 +29209,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/eslint": "^7.2.13", "eslint": "^8.15.0", @@ -29391,6 +29460,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@types/financial-times__package-json": "^1.9.0", "@types/p-retry": "^3.0.1", "winston": "^3.5.1" @@ -29440,6 +29510,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "winston": "^3.5.1" }, @@ -29566,6 +29637,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/glob": "^7.1.3", "@types/mocha": "^8.2.2", @@ -29597,6 +29669,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/jest": "^27.4.0", "winston": "^3.5.1" @@ -29719,6 +29792,9 @@ "ft-next-router": "^3.0.0", "tslib": "^2.3.1" }, + "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0" + }, "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" @@ -29850,6 +29926,9 @@ "tslib": "^2.3.1", "wait-port": "^0.2.9" }, + "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0" + }, "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" @@ -29876,6 +29955,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@types/nodemon": "^1.19.1" }, "engines": { @@ -30145,6 +30225,7 @@ "tslib": "^2.3.1" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/lodash": "^4.14.185", "winston": "^3.5.1" @@ -30225,6 +30306,9 @@ "tslib": "^2.3.1", "wait-port": "^0.2.9" }, + "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0" + }, "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" @@ -30248,6 +30332,7 @@ "@dotcom-tool-kit/types": "^3.6.0" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^29.3.1", "typescript": "^4.9.4", "winston": "^3.8.2" @@ -30462,6 +30547,7 @@ }, "devDependencies": { "@aws-sdk/types": "^3.13.1", + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/glob": "^7.1.3", "@types/jest": "^27.4.0", @@ -30493,6 +30579,7 @@ "webpack-cli": "^4.6.0" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "ts-node": "^10.0.0", "webpack": "^4.42.1", diff --git a/plugins/babel/package.json b/plugins/babel/package.json index 093022e62..6c7046664 100644 --- a/plugins/babel/package.json +++ b/plugins/babel/package.json @@ -31,6 +31,7 @@ }, "devDependencies": { "@babel/preset-env": "^7.16.11", + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "winston": "^3.5.1" }, diff --git a/plugins/babel/src/run-babel.ts b/plugins/babel/src/run-babel.ts index 60484fa9a..15ac35de6 100644 --- a/plugins/babel/src/run-babel.ts +++ b/plugins/babel/src/run-babel.ts @@ -1,6 +1,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookConsole } from '@dotcom-tool-kit/logger' -import type { BabelOptions } from '@dotcom-tool-kit/types/lib/schema/plugins/babel' +import type { BabelOptions } from '@dotcom-tool-kit/schemas/lib/plugins/babel' import * as babel from '@babel/core' import fg from 'fast-glob' import { promises as fs } from 'fs' diff --git a/plugins/babel/src/tasks/development.ts b/plugins/babel/src/tasks/development.ts index 352655aaa..affc2b700 100644 --- a/plugins/babel/src/tasks/development.ts +++ b/plugins/babel/src/tasks/development.ts @@ -1,6 +1,6 @@ import { runBabel } from '../run-babel' import { Task } from '@dotcom-tool-kit/types' -import { BabelSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/babel' +import { BabelSchema } from '@dotcom-tool-kit/schemas/lib/plugins/babel' export default class BabelDevelopment extends Task { static description = 'build babel' diff --git a/plugins/babel/src/tasks/production.ts b/plugins/babel/src/tasks/production.ts index d36f341c5..bebc35453 100644 --- a/plugins/babel/src/tasks/production.ts +++ b/plugins/babel/src/tasks/production.ts @@ -1,6 +1,6 @@ import { runBabel } from '../run-babel' import { Task } from '@dotcom-tool-kit/types' -import { BabelSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/babel' +import { BabelSchema } from '@dotcom-tool-kit/schemas/lib/plugins/babel' export default class BabelProduction extends Task { static description = 'build babel' diff --git a/plugins/babel/tsconfig.json b/plugins/babel/tsconfig.json index 3f2a5796a..755f10389 100644 --- a/plugins/babel/tsconfig.json +++ b/plugins/babel/tsconfig.json @@ -14,6 +14,9 @@ }, { "path": "../../lib/types" + }, + { + "path": "../../lib/schemas" } ] } diff --git a/plugins/cypress/package.json b/plugins/cypress/package.json index 45170d7d0..116e11caa 100644 --- a/plugins/cypress/package.json +++ b/plugins/cypress/package.json @@ -31,6 +31,7 @@ "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0" + "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/schemas": "^1.0.0" } } diff --git a/plugins/cypress/src/tasks/ci.ts b/plugins/cypress/src/tasks/ci.ts index 3ce667389..6a7d07fbb 100644 --- a/plugins/cypress/src/tasks/ci.ts +++ b/plugins/cypress/src/tasks/ci.ts @@ -2,7 +2,7 @@ import { spawn } from 'child_process' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { readState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/types' -import { CypressSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/cypress' +import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' export default class CypressCi extends Task { async run(): Promise { diff --git a/plugins/cypress/src/tasks/local.ts b/plugins/cypress/src/tasks/local.ts index 799a28a4d..5f59344dd 100644 --- a/plugins/cypress/src/tasks/local.ts +++ b/plugins/cypress/src/tasks/local.ts @@ -3,7 +3,7 @@ import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { readState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/types' -import { CypressSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/cypress' +import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' export default class CypressLocal extends Task { async run(): Promise { diff --git a/plugins/cypress/tsconfig.json b/plugins/cypress/tsconfig.json index 6b2c4da0a..ce7560f53 100644 --- a/plugins/cypress/tsconfig.json +++ b/plugins/cypress/tsconfig.json @@ -16,6 +16,9 @@ }, { "path": "../../lib/doppler" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/eslint/package.json b/plugins/eslint/package.json index b828c6a2d..56a16e6c2 100644 --- a/plugins/eslint/package.json +++ b/plugins/eslint/package.json @@ -23,6 +23,7 @@ "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/eslint", "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/eslint": "^7.2.13", "eslint": "^8.15.0", diff --git a/plugins/eslint/src/tasks/eslint.ts b/plugins/eslint/src/tasks/eslint.ts index f40b1bbf2..0477750c9 100644 --- a/plugins/eslint/src/tasks/eslint.ts +++ b/plugins/eslint/src/tasks/eslint.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { styles } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { ESLintSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/eslint' +import { ESLintSchema } from '@dotcom-tool-kit/schemas/lib/plugins/eslint' import { ESLint } from 'eslint' export default class Eslint extends Task { diff --git a/plugins/eslint/tsconfig.json b/plugins/eslint/tsconfig.json index 3f2a5796a..755f10389 100644 --- a/plugins/eslint/tsconfig.json +++ b/plugins/eslint/tsconfig.json @@ -14,6 +14,9 @@ }, { "path": "../../lib/types" + }, + { + "path": "../../lib/schemas" } ] } diff --git a/plugins/heroku/package.json b/plugins/heroku/package.json index 772fb7737..d4cb536e4 100644 --- a/plugins/heroku/package.json +++ b/plugins/heroku/package.json @@ -34,6 +34,7 @@ "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/heroku", "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@types/financial-times__package-json": "^1.9.0", "@types/p-retry": "^3.0.1", "winston": "^3.5.1" diff --git a/plugins/heroku/src/tasks/production.ts b/plugins/heroku/src/tasks/production.ts index 9a26dd60e..e5fcbb277 100644 --- a/plugins/heroku/src/tasks/production.ts +++ b/plugins/heroku/src/tasks/production.ts @@ -2,7 +2,7 @@ import { Task } from '@dotcom-tool-kit/types' import { ToolKitError } from '@dotcom-tool-kit/error' import { readState } from '@dotcom-tool-kit/state' import { styles } from '@dotcom-tool-kit/logger' -import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/heroku' +import { HerokuSchema } from '@dotcom-tool-kit/schemas/lib/plugins/heroku' import type { HerokuApiResGetApp } from 'heroku-client' import heroku, { extractHerokuError } from '../herokuClient' import { scaleDyno } from '../scaleDyno' diff --git a/plugins/heroku/src/tasks/review.ts b/plugins/heroku/src/tasks/review.ts index 0a23edc15..44c5f1afa 100644 --- a/plugins/heroku/src/tasks/review.ts +++ b/plugins/heroku/src/tasks/review.ts @@ -4,7 +4,7 @@ import { buildHerokuReviewApp } from '../buildHerokuReviewApp' import { gtg } from '../gtg' import { setStageConfigVars } from '../setConfigVars' import { writeState } from '@dotcom-tool-kit/state' -import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/heroku' +import { HerokuSchema } from '@dotcom-tool-kit/schemas/lib/plugins/heroku' import { ToolKitError } from '@dotcom-tool-kit/error' import herokuClient, { extractHerokuError } from '../herokuClient' import type { HerokuApiResPipeline } from 'heroku-client' diff --git a/plugins/heroku/src/tasks/staging.ts b/plugins/heroku/src/tasks/staging.ts index d9cce3fb1..8accf0e30 100644 --- a/plugins/heroku/src/tasks/staging.ts +++ b/plugins/heroku/src/tasks/staging.ts @@ -7,7 +7,7 @@ import { repeatedCheckForBuildSuccess } from '../repeatedCheckForBuildSuccess' import { scaleDyno } from '../scaleDyno' import { gtg } from '../gtg' import { getPipelineCouplings } from '../getPipelineCouplings' -import { HerokuSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/heroku' +import { HerokuSchema } from '@dotcom-tool-kit/schemas/lib/plugins/heroku' import { setStagingSlug } from '../setStagingSlug' export default class HerokuStaging extends Task { diff --git a/plugins/heroku/tsconfig.json b/plugins/heroku/tsconfig.json index 39fdb00f7..8fb2c32eb 100644 --- a/plugins/heroku/tsconfig.json +++ b/plugins/heroku/tsconfig.json @@ -27,6 +27,9 @@ }, { "path": "../../lib/options" + }, + { + "path": "../../lib/schemas" } ], "compilerOptions": { diff --git a/plugins/jest/package.json b/plugins/jest/package.json index beb0ba7c2..4bc9d51fd 100644 --- a/plugins/jest/package.json +++ b/plugins/jest/package.json @@ -15,8 +15,8 @@ "tslib": "^2.3.1" }, "peerDependencies": { - "jest-cli": "27.x || 28.x || 29.x", - "dotcom-tool-kit": "3.x" + "dotcom-tool-kit": "3.x", + "jest-cli": "27.x || 28.x || 29.x" }, "repository": { "type": "git", @@ -30,6 +30,7 @@ ".toolkitrc.yml" ], "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "winston": "^3.5.1" }, diff --git a/plugins/jest/src/run-jest.ts b/plugins/jest/src/run-jest.ts index 0b28ba4dc..239030774 100644 --- a/plugins/jest/src/run-jest.ts +++ b/plugins/jest/src/run-jest.ts @@ -1,6 +1,6 @@ import { fork } from 'node:child_process' import { readFile } from 'node:fs/promises' -import type { JestOptions, JestMode } from '@dotcom-tool-kit/types/lib/schema/plugins/jest' +import type { JestOptions, JestMode } from '@dotcom-tool-kit/schemas/lib/plugins/jest' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' const jestCLIPath = require.resolve('jest-cli/bin/jest') diff --git a/plugins/jest/src/tasks/ci.ts b/plugins/jest/src/tasks/ci.ts index a8135790e..eec26367e 100644 --- a/plugins/jest/src/tasks/ci.ts +++ b/plugins/jest/src/tasks/ci.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { JestSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/jest' +import { JestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/jest' import runJest from '../run-jest' export default class JestCI extends Task { diff --git a/plugins/jest/src/tasks/local.ts b/plugins/jest/src/tasks/local.ts index f0f7cda36..ed8585124 100644 --- a/plugins/jest/src/tasks/local.ts +++ b/plugins/jest/src/tasks/local.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { JestSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/jest' +import { JestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/jest' import runJest from '../run-jest' export default class JestLocal extends Task { diff --git a/plugins/jest/tsconfig.json b/plugins/jest/tsconfig.json index e8bfc4e6d..c6b10435b 100644 --- a/plugins/jest/tsconfig.json +++ b/plugins/jest/tsconfig.json @@ -10,9 +10,10 @@ }, { "path": "../../lib/logger" + }, + { + "path": "../../lib/schemas" } ], - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/plugins/mocha/package.json b/plugins/mocha/package.json index 8de061c47..a60c6b37b 100644 --- a/plugins/mocha/package.json +++ b/plugins/mocha/package.json @@ -24,6 +24,7 @@ "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/mocha", "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/glob": "^7.1.3", "@types/mocha": "^8.2.2", diff --git a/plugins/mocha/src/tasks/mocha.ts b/plugins/mocha/src/tasks/mocha.ts index 6919e6dac..7e7658c7c 100644 --- a/plugins/mocha/src/tasks/mocha.ts +++ b/plugins/mocha/src/tasks/mocha.ts @@ -1,7 +1,7 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' import { glob } from 'glob' -import { MochaSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/mocha' +import { MochaSchema } from '@dotcom-tool-kit/schemas/lib/plugins/mocha' import { fork } from 'child_process' import { promisify } from 'util' const mochaCLIPath = require.resolve('mocha/bin/mocha') diff --git a/plugins/mocha/tsconfig.json b/plugins/mocha/tsconfig.json index 84d248bcc..0d3f57ede 100644 --- a/plugins/mocha/tsconfig.json +++ b/plugins/mocha/tsconfig.json @@ -6,6 +6,9 @@ }, { "path": "../../lib/types" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"], diff --git a/plugins/n-test/package.json b/plugins/n-test/package.json index 19a8b1a97..41a8abd3b 100644 --- a/plugins/n-test/package.json +++ b/plugins/n-test/package.json @@ -24,6 +24,7 @@ "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/n-test", "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/jest": "^27.4.0", "winston": "^3.5.1" diff --git a/plugins/n-test/src/tasks/n-test.ts b/plugins/n-test/src/tasks/n-test.ts index 23d823e5d..74789068d 100644 --- a/plugins/n-test/src/tasks/n-test.ts +++ b/plugins/n-test/src/tasks/n-test.ts @@ -1,6 +1,6 @@ import { styles } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { SmokeTestSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/n-test' +import { SmokeTestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/n-test' import { SmokeTest } from '@financial-times/n-test' import { readState } from '@dotcom-tool-kit/state' diff --git a/plugins/n-test/tsconfig.json b/plugins/n-test/tsconfig.json index b6d36b494..6d8f90bbf 100644 --- a/plugins/n-test/tsconfig.json +++ b/plugins/n-test/tsconfig.json @@ -14,6 +14,9 @@ }, { "path": "../../lib/types" + }, + { + "path": "../../lib/schemas" } ] } diff --git a/plugins/next-router/package.json b/plugins/next-router/package.json index 0f220e3e9..3b3fbdf08 100644 --- a/plugins/next-router/package.json +++ b/plugins/next-router/package.json @@ -35,5 +35,8 @@ "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" + }, + "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0" } } diff --git a/plugins/next-router/src/tasks/next-router.ts b/plugins/next-router/src/tasks/next-router.ts index 87580f560..d227a3b49 100644 --- a/plugins/next-router/src/tasks/next-router.ts +++ b/plugins/next-router/src/tasks/next-router.ts @@ -5,7 +5,7 @@ import { readState } from '@dotcom-tool-kit/state' import { hookConsole, hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { ToolKitError } from '@dotcom-tool-kit/error' import { fork } from 'child_process' -import { NextRouterSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/next-router' +import { NextRouterSchema } from '@dotcom-tool-kit/schemas/lib/plugins/next-router' export default class NextRouter extends Task { static description = '' diff --git a/plugins/next-router/tsconfig.json b/plugins/next-router/tsconfig.json index 8af41e6e2..3cb96252e 100644 --- a/plugins/next-router/tsconfig.json +++ b/plugins/next-router/tsconfig.json @@ -19,6 +19,9 @@ }, { "path": "../../lib/doppler" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/node/package.json b/plugins/node/package.json index 5108917c4..ef5d10165 100644 --- a/plugins/node/package.json +++ b/plugins/node/package.json @@ -35,5 +35,8 @@ "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" + }, + "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0" } } diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index 6f6e132f0..aae2fc18f 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -2,7 +2,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookConsole, hookFork, styles } from '@dotcom-tool-kit/logger' import { writeState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/types' -import { NodeSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/node' +import { NodeSchema } from '@dotcom-tool-kit/schemas/lib/plugins/node' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { fork } from 'child_process' import getPort from 'get-port' diff --git a/plugins/node/tsconfig.json b/plugins/node/tsconfig.json index 164487c20..62e84d6ff 100644 --- a/plugins/node/tsconfig.json +++ b/plugins/node/tsconfig.json @@ -19,6 +19,9 @@ }, { "path": "../../lib/state" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/nodemon/package.json b/plugins/nodemon/package.json index 34baf961e..b899b9edc 100644 --- a/plugins/nodemon/package.json +++ b/plugins/nodemon/package.json @@ -18,8 +18,8 @@ "tslib": "^2.3.1" }, "peerDependencies": { - "nodemon": "2.x", - "dotcom-tool-kit": "3.x" + "dotcom-tool-kit": "3.x", + "nodemon": "2.x" }, "repository": { "type": "git", @@ -33,6 +33,7 @@ ".toolkitrc.yml" ], "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@types/nodemon": "^1.19.1" }, "engines": { diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index 50ec84717..5a731efa6 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -1,6 +1,6 @@ import { hookFork } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { NodemonSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/nodemon' +import { NodemonSchema } from '@dotcom-tool-kit/schemas/lib/plugins/nodemon' import { writeState } from '@dotcom-tool-kit/state' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import getPort from 'get-port' diff --git a/plugins/nodemon/tsconfig.json b/plugins/nodemon/tsconfig.json index ec6f98bae..21f58ad35 100644 --- a/plugins/nodemon/tsconfig.json +++ b/plugins/nodemon/tsconfig.json @@ -19,6 +19,9 @@ }, { "path": "../../lib/state" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/pa11y/src/tasks/pa11y.ts b/plugins/pa11y/src/tasks/pa11y.ts index f59845015..f379f1282 100644 --- a/plugins/pa11y/src/tasks/pa11y.ts +++ b/plugins/pa11y/src/tasks/pa11y.ts @@ -1,6 +1,6 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import type { Pa11ySchema } from '@dotcom-tool-kit/types/lib/schema/plugins/pa11y' +import type { Pa11ySchema } from '@dotcom-tool-kit/schemas/lib/plugins/pa11y' import { fork } from 'child_process' import { readState } from '@dotcom-tool-kit/state' diff --git a/plugins/pa11y/tsconfig.json b/plugins/pa11y/tsconfig.json index a2b756faf..13661dc57 100644 --- a/plugins/pa11y/tsconfig.json +++ b/plugins/pa11y/tsconfig.json @@ -14,6 +14,9 @@ }, { "path": "../../lib/error" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/package-json-hook/package.json b/plugins/package-json-hook/package.json index 5cd96b8bc..6247c53c7 100644 --- a/plugins/package-json-hook/package.json +++ b/plugins/package-json-hook/package.json @@ -23,6 +23,7 @@ "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/package-json-hook", "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/lodash": "^4.14.185", "winston": "^3.5.1" diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index 285b4ee5f..e2b4e4d20 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -8,7 +8,7 @@ import update from 'lodash/update' import merge from 'lodash/merge' import path from 'path' -import { PackageJsonSchema } from '@dotcom-tool-kit/types/lib/schema/hooks/package-json' +import { PackageJsonSchema } from '@dotcom-tool-kit/schemas/lib/hooks/package-json' import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' interface PackageJsonContents { diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 474b724d9..3e3616db0 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -4,7 +4,7 @@ import { promises as fs } from 'fs' import PackageJson from '../src/package-json-helper' import winston, { Logger } from 'winston' import { HookInstallation } from '@dotcom-tool-kit/types' -import { PackageJsonSchema } from '@dotcom-tool-kit/types/lib/schema/hooks/package-json' +import { PackageJsonSchema } from '@dotcom-tool-kit/schemas/lib/hooks/package-json' const logger = (winston as unknown) as Logger diff --git a/plugins/package-json-hook/tsconfig.json b/plugins/package-json-hook/tsconfig.json index 318abdeb7..409d53c66 100644 --- a/plugins/package-json-hook/tsconfig.json +++ b/plugins/package-json-hook/tsconfig.json @@ -7,6 +7,9 @@ "references": [ { "path": "../../lib/types" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/prettier/src/tasks/prettier.ts b/plugins/prettier/src/tasks/prettier.ts index 65bd1189f..9af301b0b 100644 --- a/plugins/prettier/src/tasks/prettier.ts +++ b/plugins/prettier/src/tasks/prettier.ts @@ -1,5 +1,5 @@ import prettier from 'prettier' -import { PrettierOptions, PrettierSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/prettier' +import { PrettierOptions, PrettierSchema } from '@dotcom-tool-kit/schemas/lib/plugins/prettier' import { promises as fsp } from 'fs' import fg from 'fast-glob' import { hookConsole, styles } from '@dotcom-tool-kit/logger' diff --git a/plugins/prettier/tsconfig.json b/plugins/prettier/tsconfig.json index 3f2a5796a..2a4381f2e 100644 --- a/plugins/prettier/tsconfig.json +++ b/plugins/prettier/tsconfig.json @@ -12,6 +12,9 @@ { "path": "../../lib/logger" }, + { + "path": "../../lib/schemas" + }, { "path": "../../lib/types" } diff --git a/plugins/serverless/package.json b/plugins/serverless/package.json index 2992b9e6b..62d78ba6c 100644 --- a/plugins/serverless/package.json +++ b/plugins/serverless/package.json @@ -37,5 +37,8 @@ "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" + }, + "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0" } } diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index cfa85068f..2b8ed4df5 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/serverless' +import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { getOptions } from '@dotcom-tool-kit/options' import { spawn } from 'child_process' diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index 366cb2b38..df668e339 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/serverless' +import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { spawn } from 'child_process' import { getOptions } from '@dotcom-tool-kit/options' diff --git a/plugins/serverless/src/tasks/run.ts b/plugins/serverless/src/tasks/run.ts index 240afd6e4..54287dbd9 100644 --- a/plugins/serverless/src/tasks/run.ts +++ b/plugins/serverless/src/tasks/run.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/serverless' +import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { spawn } from 'child_process' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { hookConsole, hookFork } from '@dotcom-tool-kit/logger' diff --git a/plugins/serverless/src/tasks/teardown.ts b/plugins/serverless/src/tasks/teardown.ts index 0797d126c..1e9664f25 100644 --- a/plugins/serverless/src/tasks/teardown.ts +++ b/plugins/serverless/src/tasks/teardown.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import { ServerlessSchema } from '@dotcom-tool-kit/types/lib/schema/serverless' +import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { readState } from '@dotcom-tool-kit/state' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { spawn } from 'child_process' diff --git a/plugins/serverless/tsconfig.json b/plugins/serverless/tsconfig.json index 11d6852cc..ab5835566 100644 --- a/plugins/serverless/tsconfig.json +++ b/plugins/serverless/tsconfig.json @@ -16,6 +16,9 @@ }, { "path": "../../lib/options" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/typescript/package.json b/plugins/typescript/package.json index a993977e7..6a26d9b90 100644 --- a/plugins/typescript/package.json +++ b/plugins/typescript/package.json @@ -29,6 +29,7 @@ "@dotcom-tool-kit/types": "^3.6.0" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^29.3.1", "typescript": "^4.9.4", "winston": "^3.8.2" diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index e4c4b032d..d79d11c78 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -1,6 +1,6 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/types' -import type { TypeScriptSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/typescript' +import type { TypeScriptSchema } from '@dotcom-tool-kit/schemas/lib/plugins/typescript' import { fork } from 'child_process' const tscPath = require.resolve('typescript/bin/tsc') diff --git a/plugins/typescript/tsconfig.json b/plugins/typescript/tsconfig.json index 0553e6343..beea17c63 100644 --- a/plugins/typescript/tsconfig.json +++ b/plugins/typescript/tsconfig.json @@ -10,6 +10,9 @@ }, { "path": "../../lib/types" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/upload-assets-to-s3/package.json b/plugins/upload-assets-to-s3/package.json index 194f7e1f1..263af8603 100644 --- a/plugins/upload-assets-to-s3/package.json +++ b/plugins/upload-assets-to-s3/package.json @@ -27,6 +27,7 @@ "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/upload-assets-to-s3", "devDependencies": { "@aws-sdk/types": "^3.13.1", + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/glob": "^7.1.3", "@types/jest": "^27.4.0", diff --git a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts index aa3bbda77..ddb856741 100644 --- a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts +++ b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts @@ -9,7 +9,7 @@ import { styles } from '@dotcom-tool-kit/logger' import { UploadAssetsToS3Options, UploadAssetsToS3Schema -} from '@dotcom-tool-kit/types/lib/schema/plugins/upload-assets-to-s3' +} from '@dotcom-tool-kit/schemas/lib/plugins/upload-assets-to-s3' export default class UploadAssetsToS3 extends Task { static description = '' diff --git a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts index d17f57175..098cb4a83 100644 --- a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts +++ b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach } from '@jest/globals' import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3' -import { UploadAssetsToS3Options } from '@dotcom-tool-kit/types/lib/schema/plugins/upload-assets-to-s3' +import { UploadAssetsToS3Options } from '@dotcom-tool-kit/schemas/lib/plugins/upload-assets-to-s3' import * as path from 'path' import winston, { Logger } from 'winston' import UploadAssetsToS3 from '../../src/tasks/upload-assets-to-s3' diff --git a/plugins/upload-assets-to-s3/tsconfig.json b/plugins/upload-assets-to-s3/tsconfig.json index ec7a118bb..c562891b1 100644 --- a/plugins/upload-assets-to-s3/tsconfig.json +++ b/plugins/upload-assets-to-s3/tsconfig.json @@ -13,6 +13,9 @@ }, { "path": "../../lib/types" + }, + { + "path": "../../lib/schemas" } ], "include": ["src/**/*"] diff --git a/plugins/webpack/package.json b/plugins/webpack/package.json index db60df547..20e2bb0df 100644 --- a/plugins/webpack/package.json +++ b/plugins/webpack/package.json @@ -24,10 +24,11 @@ "tslib": "^2.3.1" }, "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "dotcom-tool-kit": "3.x" + "dotcom-tool-kit": "3.x", + "webpack": "4.x.x || 5.x.x" }, "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "ts-node": "^10.0.0", "webpack": "^4.42.1", diff --git a/plugins/webpack/src/run-webpack.ts b/plugins/webpack/src/run-webpack.ts index 5ece3d837..0f0b82f1b 100644 --- a/plugins/webpack/src/run-webpack.ts +++ b/plugins/webpack/src/run-webpack.ts @@ -1,6 +1,6 @@ import { fork } from 'child_process' import { Logger } from 'winston' -import type { WebpackOptions } from '@dotcom-tool-kit/types/lib/schema/plugins/webpack' +import type { WebpackOptions } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' const webpackCLIPath = require.resolve('webpack-cli/bin/cli') diff --git a/plugins/webpack/src/tasks/development.ts b/plugins/webpack/src/tasks/development.ts index 737240b9e..3574a5588 100644 --- a/plugins/webpack/src/tasks/development.ts +++ b/plugins/webpack/src/tasks/development.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/webpack' +import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' export default class WebpackDevelopment extends Task { diff --git a/plugins/webpack/src/tasks/production.ts b/plugins/webpack/src/tasks/production.ts index d9027c27a..c4cce6a46 100644 --- a/plugins/webpack/src/tasks/production.ts +++ b/plugins/webpack/src/tasks/production.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/webpack' +import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' export default class WebpackProduction extends Task { diff --git a/plugins/webpack/src/tasks/watch.ts b/plugins/webpack/src/tasks/watch.ts index 336a34da9..99921e1e8 100644 --- a/plugins/webpack/src/tasks/watch.ts +++ b/plugins/webpack/src/tasks/watch.ts @@ -1,5 +1,5 @@ import { Task } from '@dotcom-tool-kit/types' -import { WebpackSchema } from '@dotcom-tool-kit/types/lib/schema/plugins/webpack' +import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' export default class WebpackWatch extends Task { diff --git a/plugins/webpack/tsconfig.json b/plugins/webpack/tsconfig.json index d61291136..61644460f 100644 --- a/plugins/webpack/tsconfig.json +++ b/plugins/webpack/tsconfig.json @@ -11,6 +11,9 @@ }, { "path": "../../lib/types" + }, + { + "path": "../../lib/schemas" } ] } diff --git a/tsconfig.json b/tsconfig.json index 156c0ed52..d7262bdac 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -111,6 +111,9 @@ }, { "path": "plugins/serverless" + }, + { + "path": "lib/schemas" } ] } From 9cce80af4dcb1a066d692dafaf97767ca4a59e56 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 17:14:15 +0000 Subject: [PATCH 088/321] fix: make zod peerdeps of types and schema, and explicit deps of cli and create --- core/cli/package.json | 3 +- core/create/package.json | 3 +- core/create/src/prompts/oidc.ts | 17 ++- lib/schemas/package.json | 11 +- lib/types/package.json | 9 +- package-lock.json | 118 +++++++++++++----- plugins/circleci/package.json | 6 +- plugins/circleci/src/circleci-config.ts | 2 +- plugins/package-json-hook/package.json | 6 +- .../src/package-json-helper.ts | 2 +- 10 files changed, 125 insertions(+), 52 deletions(-) diff --git a/core/cli/package.json b/core/cli/package.json index 92327a44f..d58a99fd6 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -52,7 +52,8 @@ "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", "yaml": "^1.10.2", - "zod-validation-error": "^0.3.0" + "zod": "^3.22.4", + "zod-validation-error": "^2.1.0" }, "engines": { "node": "16.x || 18.x || 20.x", diff --git a/core/create/package.json b/core/create/package.json index 897fc2cfc..b485b1645 100644 --- a/core/create/package.json +++ b/core/create/package.json @@ -31,7 +31,8 @@ "prompts": "^2.4.1", "simple-git": "^3.16.1", "tslib": "^2.3.1", - "yaml": "^2.2.1" + "yaml": "^2.2.1", + "zod": "^3.22.4" }, "repository": { "type": "git", diff --git a/core/create/src/prompts/oidc.ts b/core/create/src/prompts/oidc.ts index a55fb1d5c..2e7704251 100644 --- a/core/create/src/prompts/oidc.ts +++ b/core/create/src/prompts/oidc.ts @@ -177,12 +177,17 @@ export default async function oidcPrompt({ toolKitConfig }: OidcParams): Promise const dopplerEnvVars = new DopplerEnvVars(winstonLogger, 'prod', { project: 'dotcom-tool-kit' }) - const dopplerSecretsSchema = z.object({ - CIRCLECI_AUTH_TOKEN: z.string(), - GITHUB_ACCESS_TOKEN: z.string(), - [`AWS_${awsAccountDopplerName}_ACCESS_KEY_ID`]: z.string(), - [`AWS_${awsAccountDopplerName}_SECRET_ACCESS_KEY`]: z.string() - }) + const dopplerSecretsSchema = z + .object({ + CIRCLECI_AUTH_TOKEN: z.string(), + GITHUB_ACCESS_TOKEN: z.string() + }) + .merge( + z.object({ + [`AWS_${awsAccountDopplerName}_ACCESS_KEY_ID`]: z.string(), + [`AWS_${awsAccountDopplerName}_SECRET_ACCESS_KEY`]: z.string() + }) + ) const dopplerEnv = dopplerSecretsSchema.parse(await dopplerEnvVars.get()) let serverlessConfigRaw diff --git a/lib/schemas/package.json b/lib/schemas/package.json index 271e572a8..d0eb41d05 100644 --- a/lib/schemas/package.json +++ b/lib/schemas/package.json @@ -5,15 +5,16 @@ "main": "lib", "devDependencies": { "prompts": "^2.4.2", - "winston": "^3.11.0" + "winston": "^3.11.0", + "zod": "^3.22.4" + }, + "peerDependencies": { + "zod": "^3.22.4" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", - "license": "ISC", - "dependencies": { - "zod": "^3.20.6" - } + "license": "ISC" } diff --git a/lib/types/package.json b/lib/types/package.json index c5c2d7667..34343fdba 100644 --- a/lib/types/package.json +++ b/lib/types/package.json @@ -27,15 +27,18 @@ "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/validated": "^1.0.0", "semver": "^7.3.7", - "tslib": "^2.3.1", - "zod": "^3.20.6" + "tslib": "^2.3.1" }, "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/prompts": "^2.0.14", "@types/semver": "^7.3.9", - "winston": "^3.5.1" + "winston": "^3.5.1", + "zod": "^3.22.4" + }, + "peerDependencies": { + "zod": "^3.22.4" }, "engines": { "node": "16.x || 18.x || 20.x", diff --git a/package-lock.json b/package-lock.json index 6c9bc9652..6522ddc61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,8 @@ "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", "yaml": "^1.10.2", - "zod-validation-error": "^0.3.0" + "zod": "^3.22.4", + "zod-validation-error": "^2.1.0" }, "bin": { "dotcom-tool-kit": "bin/run" @@ -121,6 +122,25 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, + "core/cli/node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "core/cli/node_modules/zod-validation-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-2.1.0.tgz", + "integrity": "sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.18.0" + } + }, "core/create": { "name": "@dotcom-tool-kit/create", "version": "3.7.1", @@ -146,7 +166,8 @@ "prompts": "^2.4.1", "simple-git": "^3.16.1", "tslib": "^2.3.1", - "yaml": "^2.2.1" + "yaml": "^2.2.1", + "zod": "^3.22.4" }, "bin": { "create": "bin/create-tool-kit" @@ -1072,6 +1093,14 @@ "node": ">=10" } }, + "core/create/node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "core/sandbox": { "name": "@dotcom-tool-kit/sandbox", "version": "2.0.0", @@ -1213,12 +1242,13 @@ "name": "@dotcom-tool-kit/schemas", "version": "1.0.0", "license": "ISC", - "dependencies": { - "zod": "^3.20.6" - }, "devDependencies": { "prompts": "^2.4.2", - "winston": "^3.11.0" + "winston": "^3.11.0", + "zod": "^3.22.4" + }, + "peerDependencies": { + "zod": "^3.22.4" } }, "lib/schemas/node_modules/@colors/colors": { @@ -1266,6 +1296,15 @@ "node": ">= 12.0.0" } }, + "lib/schemas/node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "lib/state": { "name": "@dotcom-tool-kit/state", "version": "3.3.0", @@ -1292,19 +1331,22 @@ "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/validated": "^1.0.0", "semver": "^7.3.7", - "tslib": "^2.3.1", - "zod": "^3.20.6" + "tslib": "^2.3.1" }, "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/prompts": "^2.0.14", "@types/semver": "^7.3.9", - "winston": "^3.5.1" + "winston": "^3.5.1", + "zod": "^3.22.4" }, "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" + }, + "peerDependencies": { + "zod": "^3.22.4" } }, "lib/types/node_modules/tslib": { @@ -1312,6 +1354,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, + "lib/types/node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "lib/validated": { "name": "@dotcom-tool-kit/validated", "version": "1.0.0", @@ -28864,25 +28915,6 @@ "node": ">= 6" } }, - "node_modules/zod": { - "version": "3.20.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.20.6.tgz", - "integrity": "sha512-oyu0m54SGCtzh6EClBVqDDlAYRz4jrVtKwQ7ZnsEmMI9HnzuZFj8QFwAY1M5uniIYACdGvv0PBWPF2kO0aNofA==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-validation-error": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-0.3.1.tgz", - "integrity": "sha512-3m7VcE4YT3ZdGJoYBZnLt8E1S/r8zPFNDWMc2njaeC7Vxe5FQbgIiwHoerSkli5PgsUyxWQhpFxEAJXkBJvoDg==", - "engines": { - "node": "^14.17 || >=16.0.0" - }, - "peerDependencies": { - "zod": "^3.18.0" - } - }, "plugins/babel": { "name": "@dotcom-tool-kit/babel", "version": "3.2.0", @@ -28985,14 +29017,16 @@ "@types/jest": "^27.4.0", "@types/js-yaml": "^4.0.3", "@types/lodash": "^4.14.185", - "winston": "^3.5.1" + "winston": "^3.5.1", + "zod": "^3.22.4" }, "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { - "dotcom-tool-kit": "3.x" + "dotcom-tool-kit": "3.x", + "zod": "^3.22.4" } }, "plugins/circleci-deploy": { @@ -29163,6 +29197,15 @@ "node": ">= 14" } }, + "plugins/circleci/node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "plugins/component": { "name": "@dotcom-tool-kit/component", "version": "4.1.3", @@ -30228,11 +30271,15 @@ "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/lodash": "^4.14.185", - "winston": "^3.5.1" + "winston": "^3.5.1", + "zod": "^3.22.4" }, "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" + }, + "peerDependencies": { + "zod": "^3.22.4" } }, "plugins/package-json-hook/node_modules/tslib": { @@ -30240,6 +30287,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "plugins/package-json-hook/node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "plugins/prettier": { "name": "@dotcom-tool-kit/prettier", "version": "3.2.0", diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index a0d032ba2..929a642dc 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -32,7 +32,8 @@ "@types/jest": "^27.4.0", "@types/js-yaml": "^4.0.3", "@types/lodash": "^4.14.185", - "winston": "^3.5.1" + "winston": "^3.5.1", + "zod": "^3.22.4" }, "files": [ "/lib", @@ -42,7 +43,8 @@ "extends": "../../package.json" }, "peerDependencies": { - "dotcom-tool-kit": "3.x" + "dotcom-tool-kit": "3.x", + "zod": "^3.22.4" }, "engines": { "node": "16.x || 18.x || 20.x", diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index 0897023cf..e0f31bd3d 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -14,7 +14,7 @@ import omit from 'lodash/omit' import path from 'path' import type { PartialDeep } from 'type-fest' import YAML from 'yaml' -import { z } from 'zod' +import type { z } from 'zod' const MAJOR_ORB_VERSION = '5' diff --git a/plugins/package-json-hook/package.json b/plugins/package-json-hook/package.json index 6247c53c7..5b0a5cd57 100644 --- a/plugins/package-json-hook/package.json +++ b/plugins/package-json-hook/package.json @@ -22,11 +22,15 @@ }, "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/package-json-hook", + "peerDependencies": { + "zod": "^3.22.4" + }, "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/lodash": "^4.14.185", - "winston": "^3.5.1" + "winston": "^3.5.1", + "zod": "^3.22.4" }, "files": [ "/lib", diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index e2b4e4d20..b6a2f7a62 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -1,4 +1,4 @@ -import { z } from 'zod' +import type { z } from 'zod' import { Hook, HookInstallation, Plugin } from '@dotcom-tool-kit/types' import fs from 'fs' import get from 'lodash/get' From 5158cbb597ad9d8a32ad0e20b836396a76322e75 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 4 Jan 2024 17:04:50 +0000 Subject: [PATCH 089/321] chore: switch zod to devdependency in cli --- core/cli/package.json | 4 ++-- core/cli/src/install.ts | 2 +- package-lock.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/cli/package.json b/core/cli/package.json index d58a99fd6..fe7d0e7f7 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -37,7 +37,8 @@ "chai": "^4.3.4", "globby": "^10.0.2", "ts-node": "^8.10.2", - "winston": "^3.5.1" + "winston": "^3.5.1", + "zod": "^3.22.4" }, "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", @@ -52,7 +53,6 @@ "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", "yaml": "^1.10.2", - "zod": "^3.22.4", "zod-validation-error": "^2.1.0" }, "engines": { diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 73560acbb..ed87c2b6d 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -1,4 +1,4 @@ -import { z } from 'zod' +import type { z } from 'zod' import { ToolKitError } from '@dotcom-tool-kit/error' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' import groupBy from 'lodash/groupBy' diff --git a/package-lock.json b/package-lock.json index 6522ddc61..9e6a2aa74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,6 @@ "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", "yaml": "^1.10.2", - "zod": "^3.22.4", "zod-validation-error": "^2.1.0" }, "bin": { @@ -86,7 +85,8 @@ "chai": "^4.3.4", "globby": "^10.0.2", "ts-node": "^8.10.2", - "winston": "^3.5.1" + "winston": "^3.5.1", + "zod": "^3.22.4" }, "engines": { "node": "16.x || 18.x || 20.x", From a0643e651fc5394db2f167260406423a63f65a69 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 17:34:59 +0000 Subject: [PATCH 090/321] chore: move single(ish)-use circleci and npm definitions into those plugins --- lib/types/src/circleci.ts | 65 ----------------------- lib/types/src/npm.ts | 3 -- plugins/circleci/src/circleci-config.ts | 70 +++++++++++++++++++++++-- plugins/npm/src/tasks/publish.ts | 5 +- 4 files changed, 71 insertions(+), 72 deletions(-) delete mode 100644 lib/types/src/circleci.ts delete mode 100644 lib/types/src/npm.ts diff --git a/lib/types/src/circleci.ts b/lib/types/src/circleci.ts deleted file mode 100644 index e02526d8d..000000000 --- a/lib/types/src/circleci.ts +++ /dev/null @@ -1,65 +0,0 @@ -export const automatedComment = '# CONFIG GENERATED BY DOTCOM-TOOL-KIT, DO NOT EDIT BY HAND\n' - -export type JobConfig = { - type?: string - docker?: { image: string; environment?: Record }[] - context?: string | string[] - requires?: string[] - filters?: { branches?: { only?: string; ignore?: string }; tags?: { only?: string } } - executor?: string - [parameter: string]: unknown -} - -type TriggerConfig = { - schedule?: { cron: string; filters?: { branches: { only?: string; ignore?: string } } } -} - -export type Job = string | { [job: string]: JobConfig } - -export type Trigger = string | { [trigger: string]: TriggerConfig } - -export type Workflow = { - jobs?: Job[] - triggers?: Trigger[] -} - -export interface CircleConfig { - version: 2.1 - orbs: { - [orb: string]: string - } - executors: { - [executor: string]: { - docker: { image: string }[] - } - } - jobs: { - [job: string]: { - docker: { image: string }[] - steps: (string | { [command: string]: { path?: string } })[] - } - } - workflows: { - 'tool-kit': { - when: { - not: { - equal: ['scheduled_pipeline', '<< pipeline.trigger_source >>'] - } - } - jobs: Job[] - } - nightly: { - when: { - and: [ - { - equal: ['scheduled_pipeline', '<< pipeline.trigger_source >>'] - }, - { - equal: ['nightly', '<< pipeline.schedule.name >>'] - } - ] - } - jobs: Job[] - } - } -} diff --git a/lib/types/src/npm.ts b/lib/types/src/npm.ts deleted file mode 100644 index 20943f0c0..000000000 --- a/lib/types/src/npm.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const semVerRegex = /^v\d+\.\d+\.\d+(-.+)?/ -export const prereleaseRegex = /^v\d+\.\d+\.\d+(?:-\w+\.\d+)$/ -export const releaseRegex = /^v\d+\.\d+\.\d+$/ diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index e0f31bd3d..15bd048b0 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -2,8 +2,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { styles } from '@dotcom-tool-kit/logger' import { getOptions } from '@dotcom-tool-kit/options' import { Hook } from '@dotcom-tool-kit/types' -import { automatedComment, CircleConfig, Job, JobConfig, Workflow } from '@dotcom-tool-kit/types/lib/circleci' -import { semVerRegex } from '@dotcom-tool-kit/types/lib/npm' import { promises as fs } from 'fs' import { diffStringsUnified } from 'jest-diff' import isPlainObject from 'lodash/isPlainObject' @@ -16,6 +14,72 @@ import type { PartialDeep } from 'type-fest' import YAML from 'yaml' import type { z } from 'zod' +const automatedComment = '# CONFIG GENERATED BY DOTCOM-TOOL-KIT, DO NOT EDIT BY HAND\n' + +type JobConfig = { + type?: string + docker?: { image: string; environment?: Record }[] + context?: string | string[] + requires?: string[] + filters?: { branches?: { only?: string; ignore?: string }; tags?: { only?: string } } + executor?: string + [parameter: string]: unknown +} + +type TriggerConfig = { + schedule?: { cron: string; filters?: { branches: { only?: string; ignore?: string } } } +} + +type Job = string | { [job: string]: JobConfig } + +type Trigger = string | { [trigger: string]: TriggerConfig } + +type Workflow = { + jobs?: Job[] + triggers?: Trigger[] +} + +interface CircleConfig { + version: 2.1 + orbs: { + [orb: string]: string + } + executors: { + [executor: string]: { + docker: { image: string }[] + } + } + jobs: { + [job: string]: { + docker: { image: string }[] + steps: (string | { [command: string]: { path?: string } })[] + } + } + workflows: { + 'tool-kit': { + when: { + not: { + equal: ['scheduled_pipeline', '<< pipeline.trigger_source >>'] + } + } + jobs: Job[] + } + nightly: { + when: { + and: [ + { + equal: ['scheduled_pipeline', '<< pipeline.trigger_source >>'] + }, + { + equal: ['nightly', '<< pipeline.schedule.name >>'] + } + ] + } + jobs: Job[] + } + } +} + const MAJOR_ORB_VERSION = '5' export type CircleCIState = CircleConfig @@ -73,7 +137,7 @@ export const matrixBoilerplate = () => ({ * tagFilter sets the regex for GitHub release tags: CircleCI will ignore jobs * when doing a release if the filter isn't made explicit */ -export const tagFilter = { filters: { tags: { only: `${semVerRegex}` } } } +export const tagFilter = { filters: { tags: { only: `${/^v\d+\.\d+\.\d+(-.+)?/}` } } } /** * @deprecated explicitly using each of the objects this spreads is preferred. * jobBoilerplate is the config needed for all Tool Kit jobs in the `tool-kit` diff --git a/plugins/npm/src/tasks/publish.ts b/plugins/npm/src/tasks/publish.ts index acd2bcdc8..503036d9c 100644 --- a/plugins/npm/src/tasks/publish.ts +++ b/plugins/npm/src/tasks/publish.ts @@ -1,7 +1,6 @@ import { readFile, writeFile } from 'fs/promises' import { ToolKitError } from '@dotcom-tool-kit/error' import { Task } from '@dotcom-tool-kit/types' -import { semVerRegex, prereleaseRegex, releaseRegex } from '@dotcom-tool-kit/types/lib/npm' import pacote from 'pacote' import { readState } from '@dotcom-tool-kit/state' import pack from 'libnpmpack' @@ -13,6 +12,10 @@ import type { PackageJson } from '@npm/types' type TagType = 'prerelease' | 'latest' +const semVerRegex = /^v\d+\.\d+\.\d+(-.+)?/ +const prereleaseRegex = /^v\d+\.\d+\.\d+(?:-\w+\.\d+)$/ +const releaseRegex = /^v\d+\.\d+\.\d+$/ + export default class NpmPublish extends Task { static description = '' From c3999edeefe8c41b5ce43f4953d306bf348744fa Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 2 Jan 2024 17:37:26 +0000 Subject: [PATCH 091/321] fix: make npm publish error messages CI-agnostic --- plugins/npm/src/tasks/publish.ts | 4 ++-- plugins/npm/test/npm-publish.test.ts | 18 ++++++------------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/plugins/npm/src/tasks/publish.ts b/plugins/npm/src/tasks/publish.ts index 503036d9c..ceadda8ac 100644 --- a/plugins/npm/src/tasks/publish.ts +++ b/plugins/npm/src/tasks/publish.ts @@ -22,7 +22,7 @@ export default class NpmPublish extends Task { getNpmTag(tag: string): TagType { if (!tag) { throw new ToolKitError( - 'CIRCLE_TAG environment variable not found. Make sure you are running this on a release version!' + 'No `tag` variable found in the Tool Kit `ci` state. Make sure this task is running on a CI tag branch.' ) } if (prereleaseRegex.test(tag)) { @@ -32,7 +32,7 @@ export default class NpmPublish extends Task { return 'latest' } throw new ToolKitError( - `CIRCLE_TAG does not match regex ${semVerRegex}. Configure your release version to match the regex eg. v1.2.3-beta.8` + `The Tool Kit \`ci\` state \`tag\` variable ${tag} does not match regex ${semVerRegex}. Configure your release version to match the regex eg. v1.2.3-beta.8` ) } diff --git a/plugins/npm/test/npm-publish.test.ts b/plugins/npm/test/npm-publish.test.ts index 4747cb9f1..6e0005887 100644 --- a/plugins/npm/test/npm-publish.test.ts +++ b/plugins/npm/test/npm-publish.test.ts @@ -1,7 +1,5 @@ -import { semVerRegex } from '@dotcom-tool-kit/types/lib/npm' import NpmPublish from '../src/tasks/publish' import winston, { Logger } from 'winston' -import { ToolKitError } from '../../../lib/error/lib' import * as state from '@dotcom-tool-kit/state' import pacote, { ManifestResult } from 'pacote' import { publish } from 'libnpmpublish' @@ -38,8 +36,8 @@ describe('NpmPublish', () => { const task = new NpmPublish(logger, 'NpmPublish', {}) await expect(async () => { await task.run() - }).rejects.toThrow( - new ToolKitError(`Could not find state for ci, check that you are running this task on circleci`) + }).rejects.toThrowErrorMatchingInlineSnapshot( + `"Could not find state for ci, check that you are running this task on circleci"` ) }) @@ -49,10 +47,8 @@ describe('NpmPublish', () => { const task = new NpmPublish(logger, 'NpmPublish', {}) await expect(async () => { await task.run() - }).rejects.toThrow( - new ToolKitError( - 'CIRCLE_TAG environment variable not found. Make sure you are running this on a release version!' - ) + }).rejects.toThrowErrorMatchingInlineSnapshot( + `"No \`tag\` variable found in the Tool Kit \`ci\` state. Make sure this task is running on a CI tag branch."` ) }) @@ -72,10 +68,8 @@ describe('NpmPublish', () => { const task = new NpmPublish(logger, 'NpmPublish', {}) await expect(async () => { await task.run() - }).rejects.toThrow( - new ToolKitError( - `CIRCLE_TAG does not match regex ${semVerRegex}. Configure your release version to match the regex eg. v1.2.3-beta.8` - ) + }).rejects.toThrowErrorMatchingInlineSnapshot( + `"The Tool Kit \`ci\` state \`tag\` variable random-branch does not match regex /^v\\\\d+\\\\.\\\\d+\\\\.\\\\d+(-.+)?/. Configure your release version to match the regex eg. v1.2.3-beta.8"` ) }) From 7d0765ac8268ad60602055c7ac0c7750fa31c7f9 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 5 Jan 2024 10:02:49 +0000 Subject: [PATCH 092/321] feat: move conflict into its own package --- core/cli/package.json | 1 + core/cli/src/config.ts | 2 +- core/cli/src/install.ts | 2 +- core/cli/src/messages.ts | 2 +- core/cli/src/plugin/merge-commands.ts | 2 +- core/cli/src/plugin/merge-hooks.ts | 2 +- core/cli/src/plugin/merge-options.ts | 2 +- core/cli/src/plugin/merge-tasks.ts | 2 +- core/cli/src/plugin/options.ts | 2 +- core/cli/src/plugin/reduce-installations.ts | 2 +- core/cli/tsconfig.json | 7 ++++++- lib/conflict/package.json | 13 +++++++++++++ .../src/conflict.ts => conflict/src/index.ts} | 2 +- lib/conflict/tsconfig.json | 8 ++++++++ lib/types/package.json | 1 + lib/types/src/hook.ts | 8 ++++---- lib/types/src/index.ts | 2 +- lib/types/tsconfig.json | 3 +++ package-lock.json | 13 +++++++++++++ plugins/package-json-hook/package.json | 1 + .../package-json-hook/src/package-json-helper.ts | 2 +- plugins/package-json-hook/tsconfig.json | 7 ++++++- 22 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 lib/conflict/package.json rename lib/{types/src/conflict.ts => conflict/src/index.ts} (94%) create mode 100644 lib/conflict/tsconfig.json diff --git a/core/cli/package.json b/core/cli/package.json index fe7d0e7f7..ab90d9084 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -41,6 +41,7 @@ "zod": "^3.22.4" }, "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/options": "^3.2.0", diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 32abf6d02..785b8b61b 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -7,7 +7,7 @@ import { withoutConflicts, isConflict, findConflictingEntries -} from '@dotcom-tool-kit/types/lib/conflict' +} from '@dotcom-tool-kit/conflict' import { ToolKitConflictError } from '@dotcom-tool-kit/error' import { RawConfig, ValidConfig, ValidPluginsConfig } from '@dotcom-tool-kit/types' import { diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index ed87c2b6d..16c6a7dfe 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -8,7 +8,7 @@ import { hasConfigChanged, updateHashes } from './config/hash' import { Hook, HookClass, ValidConfig } from '@dotcom-tool-kit/types' import { Validated, invalid, reduceValidated, valid } from '@dotcom-tool-kit/validated' import { reducePluginHookInstallations } from './plugin/reduce-installations' -import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/types/src/conflict' +import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/conflict' import { HookOptions, HookSchemas } from '@dotcom-tool-kit/schemas' import { formatUninstalledHooks } from './messages' import { importEntryPoint } from './plugin/entry-point' diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 6feab673c..14daf1e1f 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -2,7 +2,7 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' import type { CommandTask, EntryPoint, Hook, Plugin, PluginOptions } from '@dotcom-tool-kit/types' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' -import type { Conflict } from '@dotcom-tool-kit/types/lib/conflict' +import type { Conflict } from '@dotcom-tool-kit/conflict' const formatTaskConflict = ([key, conflict]: [string, Conflict]): string => `- ${s.task(key ?? 'unknown task')} ${s.dim('from plugins')} ${conflict.conflicting diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts index 8e2f94ee4..55eeef745 100644 --- a/core/cli/src/plugin/merge-commands.ts +++ b/core/cli/src/plugin/merge-commands.ts @@ -1,5 +1,5 @@ import { CommandTask, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' -import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { isDescendent } from './is-descendent' export const mergePluginCommands = (config: ValidPluginsConfig, plugin: Plugin) => { diff --git a/core/cli/src/plugin/merge-hooks.ts b/core/cli/src/plugin/merge-hooks.ts index 91e7f2610..cc06d16e3 100644 --- a/core/cli/src/plugin/merge-hooks.ts +++ b/core/cli/src/plugin/merge-hooks.ts @@ -1,5 +1,5 @@ import { EntryPoint, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' -import { isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { isConflict } from '@dotcom-tool-kit/conflict' export const mergePluginHooks = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { diff --git a/core/cli/src/plugin/merge-options.ts b/core/cli/src/plugin/merge-options.ts index 9b3095f5a..60f72f876 100644 --- a/core/cli/src/plugin/merge-options.ts +++ b/core/cli/src/plugin/merge-options.ts @@ -1,6 +1,6 @@ import { Plugin, PluginOptions, ValidPluginsConfig } from '@dotcom-tool-kit/types' import { isDescendent } from './is-descendent' -import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' // merge options from this plugin's config with any options we've collected already // TODO this is almost the exact same code as for command tasks, refactor diff --git a/core/cli/src/plugin/merge-tasks.ts b/core/cli/src/plugin/merge-tasks.ts index 5977d11e1..1dd97cad8 100644 --- a/core/cli/src/plugin/merge-tasks.ts +++ b/core/cli/src/plugin/merge-tasks.ts @@ -1,5 +1,5 @@ import { EntryPoint, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' -import { isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { isConflict } from '@dotcom-tool-kit/conflict' // add plugin tasks to our task registry, handling any conflicts export const mergePluginTasks = (config: ValidPluginsConfig, plugin: Plugin) => { diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index 3fd87a944..d971409e6 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -1,7 +1,7 @@ import { ValidPluginsConfig } from '@dotcom-tool-kit/types' import { InvalidOption } from '../messages' import { SchemaOptions, PluginSchemas } from '@dotcom-tool-kit/schemas' -import { isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { isConflict } from '@dotcom-tool-kit/conflict' import type { Logger } from 'winston' export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig): InvalidOption[] => { diff --git a/core/cli/src/plugin/reduce-installations.ts b/core/cli/src/plugin/reduce-installations.ts index 67d0339ae..5a310aa85 100644 --- a/core/cli/src/plugin/reduce-installations.ts +++ b/core/cli/src/plugin/reduce-installations.ts @@ -1,6 +1,6 @@ import { Logger } from 'winston' import { HookClass, HookInstallation, Plugin, ValidConfig } from '@dotcom-tool-kit/types' -import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { groupBy } from 'lodash' import { HookSchemas, HookOptions } from '@dotcom-tool-kit/schemas' diff --git a/core/cli/tsconfig.json b/core/cli/tsconfig.json index 2b448aa0c..5f51fbfe2 100644 --- a/core/cli/tsconfig.json +++ b/core/cli/tsconfig.json @@ -15,11 +15,16 @@ }, { "path": "../../lib/validated" + }, + { + "path": "../../lib/conflict" } ], "compilerOptions": { "outDir": "lib", "rootDir": "src" }, - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/lib/conflict/package.json b/lib/conflict/package.json new file mode 100644 index 000000000..ce8695fe4 --- /dev/null +++ b/lib/conflict/package.json @@ -0,0 +1,13 @@ +{ + "name": "@dotcom-tool-kit/conflict", + "version": "1.0.0", + "description": "", + "main": "lib", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/lib/types/src/conflict.ts b/lib/conflict/src/index.ts similarity index 94% rename from lib/types/src/conflict.ts rename to lib/conflict/src/index.ts index dba0be814..2000faf98 100644 --- a/lib/types/src/conflict.ts +++ b/lib/conflict/src/index.ts @@ -1,4 +1,4 @@ -import type { Plugin } from './index' +import type { Plugin } from '../../types/src/index' export interface Conflict { plugin: Plugin diff --git a/lib/conflict/tsconfig.json b/lib/conflict/tsconfig.json new file mode 100644 index 000000000..c998ec643 --- /dev/null +++ b/lib/conflict/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.settings.json", + "references": [], + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + } +} diff --git a/lib/types/package.json b/lib/types/package.json index 34343fdba..558552759 100644 --- a/lib/types/package.json +++ b/lib/types/package.json @@ -23,6 +23,7 @@ "extends": "../../package.json" }, "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/validated": "^1.0.0", diff --git a/lib/types/src/hook.ts b/lib/types/src/hook.ts index 91fd9a2cd..805af1d3e 100644 --- a/lib/types/src/hook.ts +++ b/lib/types/src/hook.ts @@ -1,9 +1,9 @@ import type { Logger } from 'winston' -import { Base } from './base' -import { hookSymbol, typeSymbol } from './symbols' +import { Base } from '../../types/src/base' +import { hookSymbol, typeSymbol } from '../../types/src/symbols' import { z } from 'zod' -import { Plugin } from './index' -import { Conflict, isConflict } from './conflict' +import { Plugin } from '../../types/src/index' +import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' export interface HookInstallation> { options: Options diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 36418f4b0..216103ac5 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -1,4 +1,4 @@ -import type { Conflict } from './conflict' +import type { Conflict } from '@dotcom-tool-kit/conflict' import type { Validated } from '@dotcom-tool-kit/validated' import type { SchemaOptions } from '@dotcom-tool-kit/schemas' diff --git a/lib/types/tsconfig.json b/lib/types/tsconfig.json index 4c2c21267..041f6efbe 100644 --- a/lib/types/tsconfig.json +++ b/lib/types/tsconfig.json @@ -12,6 +12,9 @@ }, { "path": "../schemas" + }, + { + "path": "../conflict" } ], "compilerOptions": { diff --git a/package-lock.json b/package-lock.json index 9e6a2aa74..8052af812 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "version": "3.4.5", "license": "MIT", "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/options": "^3.2.0", @@ -1130,6 +1131,12 @@ "npm": "7.x || 8.x || 9.x" } }, + "lib/conflict": { + "name": "@dotcom-tool-kit/conflict", + "version": "1.0.0", + "license": "ISC", + "devDependencies": {} + }, "lib/doppler": { "name": "@dotcom-tool-kit/doppler", "version": "1.1.0", @@ -1327,6 +1334,7 @@ "version": "3.6.0", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/validated": "^1.0.0", @@ -6330,6 +6338,10 @@ "resolved": "plugins/component", "link": true }, + "node_modules/@dotcom-tool-kit/conflict": { + "resolved": "lib/conflict", + "link": true + }, "node_modules/@dotcom-tool-kit/create": { "resolved": "core/create", "link": true @@ -30262,6 +30274,7 @@ "version": "4.2.0", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/types": "^3.4.0", "@financial-times/package-json": "^3.0.0", "lodash": "^4.17.21", diff --git a/plugins/package-json-hook/package.json b/plugins/package-json-hook/package.json index 5b0a5cd57..119de1e4a 100644 --- a/plugins/package-json-hook/package.json +++ b/plugins/package-json-hook/package.json @@ -10,6 +10,7 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/types": "^3.4.0", "@financial-times/package-json": "^3.0.0", "lodash": "^4.17.21", diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index b6a2f7a62..59a10fac6 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -9,7 +9,7 @@ import merge from 'lodash/merge' import path from 'path' import { PackageJsonSchema } from '@dotcom-tool-kit/schemas/lib/hooks/package-json' -import { Conflict, isConflict } from '@dotcom-tool-kit/types/src/conflict' +import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' interface PackageJsonContents { [field: string]: PackageJsonContents | string diff --git a/plugins/package-json-hook/tsconfig.json b/plugins/package-json-hook/tsconfig.json index 409d53c66..c7091d69d 100644 --- a/plugins/package-json-hook/tsconfig.json +++ b/plugins/package-json-hook/tsconfig.json @@ -10,7 +10,12 @@ }, { "path": "../../lib/schemas" + }, + { + "path": "../../lib/conflict" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } From 6cc09b5a0afb136810f8e9fa45dea7aa0a10d830 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 5 Jan 2024 12:45:10 +0000 Subject: [PATCH 093/321] feat!: move base classes into their own package --- core/cli/package.json | 1 + core/cli/src/init.ts | 2 +- core/cli/src/install.ts | 2 +- core/cli/src/messages.ts | 2 +- core/cli/src/tasks.ts | 2 +- lib/base/package.json | 15 +++++ lib/{types => base}/src/base.ts | 2 +- lib/{types => base}/src/hook.ts | 4 +- lib/base/src/index.ts | 4 ++ lib/{types => base}/src/init.ts | 0 lib/{types => base}/src/symbols.ts | 0 lib/{types => base}/src/task.ts | 0 lib/base/tsconfig.json | 12 ++++ lib/types/src/index.ts | 4 -- package-lock.json | 60 ++++++++++++------- plugins/babel/package.json | 2 +- plugins/babel/src/tasks/development.ts | 2 +- plugins/babel/src/tasks/production.ts | 2 +- plugins/babel/tsconfig.json | 6 +- plugins/circleci-deploy/tsconfig.json | 6 +- plugins/circleci-npm/tsconfig.json | 4 +- plugins/circleci/package.json | 2 +- plugins/circleci/src/circleci-config.ts | 2 +- plugins/circleci/src/init-env-vars.ts | 2 +- plugins/circleci/tsconfig.json | 6 +- plugins/component/tsconfig.json | 6 +- plugins/cypress/package.json | 6 +- plugins/cypress/src/tasks/ci.ts | 2 +- plugins/cypress/src/tasks/local.ts | 2 +- plugins/cypress/tsconfig.json | 6 +- plugins/eslint/package.json | 2 +- plugins/eslint/src/tasks/eslint.ts | 2 +- plugins/eslint/tsconfig.json | 6 +- plugins/heroku/package.json | 2 +- plugins/heroku/src/tasks/production.ts | 2 +- plugins/heroku/src/tasks/review.ts | 2 +- plugins/heroku/src/tasks/staging.ts | 2 +- plugins/heroku/src/tasks/teardown.ts | 2 +- plugins/heroku/tsconfig.json | 6 +- plugins/jest/package.json | 2 +- plugins/jest/src/tasks/ci.ts | 2 +- plugins/jest/src/tasks/local.ts | 2 +- plugins/jest/tsconfig.json | 6 +- plugins/lint-staged/package.json | 2 +- plugins/lint-staged/src/tasks/lint-staged.ts | 2 +- plugins/mocha/package.json | 2 +- plugins/mocha/src/tasks/mocha.ts | 2 +- plugins/mocha/tsconfig.json | 11 +++- plugins/n-test/package.json | 2 +- plugins/n-test/src/tasks/n-test.ts | 2 +- plugins/n-test/tsconfig.json | 6 +- plugins/next-router/package.json | 6 +- plugins/next-router/src/tasks/next-router.ts | 2 +- plugins/next-router/tsconfig.json | 6 +- plugins/node/package.json | 2 +- plugins/node/src/tasks/node.ts | 2 +- plugins/node/tsconfig.json | 6 +- plugins/nodemon/package.json | 2 +- plugins/nodemon/src/tasks/nodemon.ts | 2 +- plugins/nodemon/tsconfig.json | 6 +- plugins/npm/package.json | 2 +- plugins/npm/src/tasks/prune.ts | 2 +- plugins/npm/src/tasks/publish.ts | 2 +- plugins/npm/tsconfig.json | 6 +- plugins/pa11y/package.json | 2 +- plugins/pa11y/src/tasks/pa11y.ts | 2 +- plugins/pa11y/tsconfig.json | 11 +++- plugins/package-json-hook/package.json | 2 +- .../src/package-json-helper.ts | 2 +- plugins/package-json-hook/test/index.test.ts | 2 +- plugins/package-json-hook/tsconfig.json | 2 +- plugins/prettier/package.json | 2 +- plugins/prettier/src/tasks/prettier.ts | 2 +- plugins/prettier/tsconfig.json | 6 +- plugins/serverless/package.json | 2 +- plugins/serverless/src/tasks/deploy.ts | 2 +- plugins/serverless/src/tasks/provision.ts | 2 +- plugins/serverless/src/tasks/run.ts | 2 +- plugins/serverless/src/tasks/teardown.ts | 2 +- plugins/serverless/tsconfig.json | 6 +- plugins/typescript/package.json | 4 +- plugins/typescript/src/tasks/typescript.ts | 2 +- plugins/typescript/tsconfig.json | 6 +- plugins/upload-assets-to-s3/package.json | 2 +- .../src/tasks/upload-assets-to-s3.ts | 2 +- plugins/upload-assets-to-s3/tsconfig.json | 6 +- plugins/webpack/package.json | 2 +- plugins/webpack/src/tasks/development.ts | 2 +- plugins/webpack/src/tasks/production.ts | 2 +- plugins/webpack/src/tasks/watch.ts | 2 +- plugins/webpack/tsconfig.json | 6 +- 91 files changed, 227 insertions(+), 137 deletions(-) create mode 100644 lib/base/package.json rename lib/{types => base}/src/base.ts (98%) rename lib/{types => base}/src/hook.ts (95%) create mode 100644 lib/base/src/index.ts rename lib/{types => base}/src/init.ts (100%) rename lib/{types => base}/src/symbols.ts (100%) rename lib/{types => base}/src/task.ts (100%) create mode 100644 lib/base/tsconfig.json diff --git a/core/cli/package.json b/core/cli/package.json index ab90d9084..cc6021ed7 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -41,6 +41,7 @@ "zod": "^3.22.4" }, "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", diff --git a/core/cli/src/init.ts b/core/cli/src/init.ts index 5f46d1096..db80f8195 100644 --- a/core/cli/src/init.ts +++ b/core/cli/src/init.ts @@ -1,4 +1,4 @@ -import { Init, InitClass, ValidConfig } from '@dotcom-tool-kit/types' +import { Init, InitClass, ValidConfig } from '@dotcom-tool-kit/base' import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' import { Logger } from 'winston' import { importEntryPoint } from './plugin/entry-point' diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 16c6a7dfe..0ff4ddbe9 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -5,7 +5,7 @@ import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' import { loadConfig } from './config' import { hasConfigChanged, updateHashes } from './config/hash' -import { Hook, HookClass, ValidConfig } from '@dotcom-tool-kit/types' +import { Hook, HookClass, ValidConfig } from '@dotcom-tool-kit/base' import { Validated, invalid, reduceValidated, valid } from '@dotcom-tool-kit/validated' import { reducePluginHookInstallations } from './plugin/reduce-installations' import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/conflict' diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 14daf1e1f..e5aa91bd5 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -1,5 +1,5 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' -import type { CommandTask, EntryPoint, Hook, Plugin, PluginOptions } from '@dotcom-tool-kit/types' +import type { CommandTask, EntryPoint, Hook, Plugin, PluginOptions } from '@dotcom-tool-kit/base' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' import type { Conflict } from '@dotcom-tool-kit/conflict' diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 47ee5b7b7..e9c010dab 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -1,4 +1,4 @@ -import { Task, TaskConstructor, ValidConfig } from '@dotcom-tool-kit/types' +import { Task, TaskConstructor, ValidConfig } from '@dotcom-tool-kit/base' import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' import type { Logger } from 'winston' import { importEntryPoint } from './plugin/entry-point' diff --git a/lib/base/package.json b/lib/base/package.json new file mode 100644 index 000000000..30346310a --- /dev/null +++ b/lib/base/package.json @@ -0,0 +1,15 @@ +{ + "name": "@dotcom-tool-kit/base", + "version": "3.4.1", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0" + } +} diff --git a/lib/types/src/base.ts b/lib/base/src/base.ts similarity index 98% rename from lib/types/src/base.ts rename to lib/base/src/base.ts index 361fc3402..6d4930f1e 100644 --- a/lib/types/src/base.ts +++ b/lib/base/src/base.ts @@ -50,7 +50,7 @@ export abstract class Base { } else { return invalid([ `object is from an outdated version of ${s.plugin( - '@dotcom-tool-kit/types' + '@dotcom-tool-kit/base' )}, make sure you're using at least version ${s.heading(this.version)} of the plugin` ]) } diff --git a/lib/types/src/hook.ts b/lib/base/src/hook.ts similarity index 95% rename from lib/types/src/hook.ts rename to lib/base/src/hook.ts index 805af1d3e..01ae0900f 100644 --- a/lib/types/src/hook.ts +++ b/lib/base/src/hook.ts @@ -1,6 +1,6 @@ import type { Logger } from 'winston' -import { Base } from '../../types/src/base' -import { hookSymbol, typeSymbol } from '../../types/src/symbols' +import { Base } from './base' +import { hookSymbol, typeSymbol } from './symbols' import { z } from 'zod' import { Plugin } from '../../types/src/index' import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' diff --git a/lib/base/src/index.ts b/lib/base/src/index.ts new file mode 100644 index 000000000..7bbac03f1 --- /dev/null +++ b/lib/base/src/index.ts @@ -0,0 +1,4 @@ +export * from './base' +export * from './hook' +export * from './init' +export * from './task' diff --git a/lib/types/src/init.ts b/lib/base/src/init.ts similarity index 100% rename from lib/types/src/init.ts rename to lib/base/src/init.ts diff --git a/lib/types/src/symbols.ts b/lib/base/src/symbols.ts similarity index 100% rename from lib/types/src/symbols.ts rename to lib/base/src/symbols.ts diff --git a/lib/types/src/task.ts b/lib/base/src/task.ts similarity index 100% rename from lib/types/src/task.ts rename to lib/base/src/task.ts diff --git a/lib/base/tsconfig.json b/lib/base/tsconfig.json new file mode 100644 index 000000000..aa314f95c --- /dev/null +++ b/lib/base/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.settings.json", + "references": [ + { + "path": "../conflict" + } + ], + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + } +} diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts index 216103ac5..4e030b2dd 100644 --- a/lib/types/src/index.ts +++ b/lib/types/src/index.ts @@ -3,10 +3,6 @@ import type { Validated } from '@dotcom-tool-kit/validated' import type { SchemaOptions } from '@dotcom-tool-kit/schemas' export * from '@dotcom-tool-kit/validated' -export * from './base' -export * from './task' -export * from './hook' -export * from './init' export type RCFile = { plugins: string[] diff --git a/package-lock.json b/package-lock.json index 8052af812..47f66be87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "version": "3.4.5", "license": "MIT", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", @@ -1131,6 +1132,13 @@ "npm": "7.x || 8.x || 9.x" } }, + "lib/base": { + "version": "3.4.1", + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0" + } + }, "lib/conflict": { "name": "@dotcom-tool-kit/conflict", "version": "1.0.0", @@ -6318,6 +6326,10 @@ "resolved": "plugins/backend-serverless-app", "link": true }, + "node_modules/@dotcom-tool-kit/base": { + "resolved": "lib/base", + "link": true + }, "node_modules/@dotcom-tool-kit/circleci": { "resolved": "plugins/circleci", "link": true @@ -28932,9 +28944,9 @@ "version": "3.2.0", "license": "MIT", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "fast-glob": "^3.2.11", "tslib": "^2.3.1" }, @@ -29014,10 +29026,10 @@ "version": "6.0.1", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "jest-diff": "^29.5.0", "lodash": "^4.17.21", "tslib": "^2.3.1", @@ -29239,11 +29251,13 @@ "version": "4.0.1", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/schemas": "^1.0.0", - "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0" + "@dotcom-tool-kit/state": "^3.3.0" + }, + "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0" }, "engines": { "node": "16.x || 18.x || 20.x", @@ -29258,9 +29272,9 @@ "version": "3.2.0", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "tslib": "^2.3.1" }, "devDependencies": { @@ -29498,6 +29512,7 @@ "version": "3.4.1", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", @@ -29505,7 +29520,6 @@ "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "@octokit/request": "^5.6.0", "@octokit/request-error": "^2.1.0", @@ -29560,8 +29574,8 @@ "version": "3.4.0", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "tslib": "^2.3.1" }, "devDependencies": { @@ -29588,9 +29602,9 @@ "version": "4.2.0", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", - "@dotcom-tool-kit/types": "^3.6.0", "lint-staged": "^11.2.3", "tslib": "^2.3.1" }, @@ -29685,9 +29699,9 @@ "version": "3.2.0", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "glob": "^7.1.7", "tslib": "^2.3.1" }, @@ -29717,9 +29731,9 @@ "version": "3.3.1", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "@financial-times/n-test": "^6.1.0-beta.1", "tslib": "^2.3.1" }, @@ -29839,11 +29853,11 @@ "version": "3.4.1", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "ft-next-router": "^3.0.0", "tslib": "^2.3.1" }, @@ -29973,10 +29987,10 @@ "version": "3.4.1", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "get-port": "^5.1.1", "tslib": "^2.3.1", "wait-port": "^0.2.9" @@ -30002,10 +30016,10 @@ "version": "3.4.1", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "get-port": "^5.1.1", "tslib": "^2.3.1" }, @@ -30033,10 +30047,10 @@ "license": "ISC", "dependencies": { "@actions/exec": "^1.1.0", + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "libnpmpack": "^3.1.0", "libnpmpublish": "^5.0.1", "pacote": "^12.0.3", @@ -30249,7 +30263,7 @@ "version": "0.5.2", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/base": "^3.4.1", "pa11y-ci": "^3.0.1", "tslib": "^2.3.1" }, @@ -30274,8 +30288,8 @@ "version": "4.2.0", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/conflict": "^1.0.0", - "@dotcom-tool-kit/types": "^3.4.0", "@financial-times/package-json": "^3.0.0", "lodash": "^4.17.21", "tslib": "^2.3.1" @@ -30314,10 +30328,10 @@ "version": "3.2.0", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", - "@dotcom-tool-kit/types": "^3.6.0", "fast-glob": "^3.2.7", "hook-std": "^2.0.0", "prettier": "^2.2.1", @@ -30366,11 +30380,11 @@ "version": "2.4.4", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "get-port": "^5.1.1", "tslib": "^2.3.1", "wait-port": "^0.2.9" @@ -30397,8 +30411,8 @@ "version": "2.2.0", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0" + "@dotcom-tool-kit/base": "^3.4.1", + "@dotcom-tool-kit/logger": "^3.4.0" }, "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0", @@ -30607,9 +30621,9 @@ "license": "ISC", "dependencies": { "@aws-sdk/client-s3": "^3.256.0", + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "glob": "^7.1.6", "mime": "^2.5.2", "tslib": "^2.3.1" @@ -30641,9 +30655,9 @@ "version": "3.2.0", "license": "MIT", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "tslib": "^2.3.1", "webpack-cli": "^4.6.0" }, diff --git a/plugins/babel/package.json b/plugins/babel/package.json index 6c7046664..caeb26d50 100644 --- a/plugins/babel/package.json +++ b/plugins/babel/package.json @@ -16,9 +16,9 @@ }, "keywords": [], "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "fast-glob": "^3.2.11", "tslib": "^2.3.1" }, diff --git a/plugins/babel/src/tasks/development.ts b/plugins/babel/src/tasks/development.ts index affc2b700..23e9b2465 100644 --- a/plugins/babel/src/tasks/development.ts +++ b/plugins/babel/src/tasks/development.ts @@ -1,5 +1,5 @@ import { runBabel } from '../run-babel' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { BabelSchema } from '@dotcom-tool-kit/schemas/lib/plugins/babel' export default class BabelDevelopment extends Task { diff --git a/plugins/babel/src/tasks/production.ts b/plugins/babel/src/tasks/production.ts index bebc35453..8007ac9f1 100644 --- a/plugins/babel/src/tasks/production.ts +++ b/plugins/babel/src/tasks/production.ts @@ -1,5 +1,5 @@ import { runBabel } from '../run-babel' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { BabelSchema } from '@dotcom-tool-kit/schemas/lib/plugins/babel' export default class BabelProduction extends Task { diff --git a/plugins/babel/tsconfig.json b/plugins/babel/tsconfig.json index 755f10389..459bea939 100644 --- a/plugins/babel/tsconfig.json +++ b/plugins/babel/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.settings.json", - "include": ["src/**/*"], + "include": [ + "src/**/*" + ], "compilerOptions": { "outDir": "lib", "rootDir": "src" @@ -13,7 +15,7 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/schemas" diff --git a/plugins/circleci-deploy/tsconfig.json b/plugins/circleci-deploy/tsconfig.json index 853368ad2..e5f0bccf7 100644 --- a/plugins/circleci-deploy/tsconfig.json +++ b/plugins/circleci-deploy/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/options" @@ -15,5 +15,7 @@ "path": "../circleci" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/circleci-npm/tsconfig.json b/plugins/circleci-npm/tsconfig.json index 1ce32d331..5428d7010 100644 --- a/plugins/circleci-npm/tsconfig.json +++ b/plugins/circleci-npm/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../circleci" @@ -18,4 +18,4 @@ "include": [ "src/**/*" ] -} \ No newline at end of file +} diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 929a642dc..f861e9dc0 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -7,10 +7,10 @@ "test": "cd ../../ ; npx jest --silent --projects plugins/circleci" }, "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "jest-diff": "^29.5.0", "lodash": "^4.17.21", "tslib": "^2.3.1", diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index 15bd048b0..baf18dc1a 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { styles } from '@dotcom-tool-kit/logger' import { getOptions } from '@dotcom-tool-kit/options' -import { Hook } from '@dotcom-tool-kit/types' +import { Hook } from '@dotcom-tool-kit/base' import { promises as fs } from 'fs' import { diffStringsUnified } from 'jest-diff' import isPlainObject from 'lodash/isPlainObject' diff --git a/plugins/circleci/src/init-env-vars.ts b/plugins/circleci/src/init-env-vars.ts index 50b78cdfb..20a32862b 100644 --- a/plugins/circleci/src/init-env-vars.ts +++ b/plugins/circleci/src/init-env-vars.ts @@ -1,5 +1,5 @@ import { writeState } from '@dotcom-tool-kit/state' -import { Init } from '@dotcom-tool-kit/types' +import { Init } from '@dotcom-tool-kit/base' export default class CircleCIEnvVars extends Init { async init() { diff --git a/plugins/circleci/tsconfig.json b/plugins/circleci/tsconfig.json index 9b0214cce..b9d99f9a1 100644 --- a/plugins/circleci/tsconfig.json +++ b/plugins/circleci/tsconfig.json @@ -11,7 +11,7 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/options" @@ -21,5 +21,7 @@ "outDir": "lib", "rootDir": "src" }, - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/component/tsconfig.json b/plugins/component/tsconfig.json index 318abdeb7..6dfb3f60a 100644 --- a/plugins/component/tsconfig.json +++ b/plugins/component/tsconfig.json @@ -6,8 +6,10 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/cypress/package.json b/plugins/cypress/package.json index 116e11caa..b335be8f8 100644 --- a/plugins/cypress/package.json +++ b/plugins/cypress/package.json @@ -28,10 +28,12 @@ "npm": "7.x || 8.x || 9.x || 10.x" }, "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/state": "^3.3.0" + }, + "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0" } } diff --git a/plugins/cypress/src/tasks/ci.ts b/plugins/cypress/src/tasks/ci.ts index 6a7d07fbb..03edc3cd9 100644 --- a/plugins/cypress/src/tasks/ci.ts +++ b/plugins/cypress/src/tasks/ci.ts @@ -1,7 +1,7 @@ import { spawn } from 'child_process' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { readState } from '@dotcom-tool-kit/state' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' export default class CypressCi extends Task { diff --git a/plugins/cypress/src/tasks/local.ts b/plugins/cypress/src/tasks/local.ts index 5f59344dd..67c3e0fa1 100644 --- a/plugins/cypress/src/tasks/local.ts +++ b/plugins/cypress/src/tasks/local.ts @@ -2,7 +2,7 @@ import { spawn } from 'child_process' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { readState } from '@dotcom-tool-kit/state' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' export default class CypressLocal extends Task { diff --git a/plugins/cypress/tsconfig.json b/plugins/cypress/tsconfig.json index ce7560f53..bc02a1f0b 100644 --- a/plugins/cypress/tsconfig.json +++ b/plugins/cypress/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/logger" @@ -21,5 +21,7 @@ "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/eslint/package.json b/plugins/eslint/package.json index 56a16e6c2..1919c9b98 100644 --- a/plugins/eslint/package.json +++ b/plugins/eslint/package.json @@ -10,9 +10,9 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "tslib": "^2.3.1" }, "repository": { diff --git a/plugins/eslint/src/tasks/eslint.ts b/plugins/eslint/src/tasks/eslint.ts index 0477750c9..829a869bd 100644 --- a/plugins/eslint/src/tasks/eslint.ts +++ b/plugins/eslint/src/tasks/eslint.ts @@ -1,6 +1,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { styles } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ESLintSchema } from '@dotcom-tool-kit/schemas/lib/plugins/eslint' import { ESLint } from 'eslint' diff --git a/plugins/eslint/tsconfig.json b/plugins/eslint/tsconfig.json index 755f10389..459bea939 100644 --- a/plugins/eslint/tsconfig.json +++ b/plugins/eslint/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.settings.json", - "include": ["src/**/*"], + "include": [ + "src/**/*" + ], "compilerOptions": { "outDir": "lib", "rootDir": "src" @@ -13,7 +15,7 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/schemas" diff --git a/plugins/heroku/package.json b/plugins/heroku/package.json index d4cb536e4..e3a44ce52 100644 --- a/plugins/heroku/package.json +++ b/plugins/heroku/package.json @@ -10,6 +10,7 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", @@ -17,7 +18,6 @@ "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "@octokit/request": "^5.6.0", "@octokit/request-error": "^2.1.0", diff --git a/plugins/heroku/src/tasks/production.ts b/plugins/heroku/src/tasks/production.ts index e5fcbb277..9249e8965 100644 --- a/plugins/heroku/src/tasks/production.ts +++ b/plugins/heroku/src/tasks/production.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ToolKitError } from '@dotcom-tool-kit/error' import { readState } from '@dotcom-tool-kit/state' import { styles } from '@dotcom-tool-kit/logger' diff --git a/plugins/heroku/src/tasks/review.ts b/plugins/heroku/src/tasks/review.ts index 44c5f1afa..71cd4b128 100644 --- a/plugins/heroku/src/tasks/review.ts +++ b/plugins/heroku/src/tasks/review.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { getHerokuReviewApp } from '../getHerokuReviewApp' import { buildHerokuReviewApp } from '../buildHerokuReviewApp' import { gtg } from '../gtg' diff --git a/plugins/heroku/src/tasks/staging.ts b/plugins/heroku/src/tasks/staging.ts index 8accf0e30..1ffeef9bf 100644 --- a/plugins/heroku/src/tasks/staging.ts +++ b/plugins/heroku/src/tasks/staging.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ToolKitError } from '@dotcom-tool-kit/error' import { getHerokuStagingApp } from '../getHerokuStagingApp' import { setAppConfigVars } from '../setConfigVars' diff --git a/plugins/heroku/src/tasks/teardown.ts b/plugins/heroku/src/tasks/teardown.ts index 92e7ae836..695f86ed8 100644 --- a/plugins/heroku/src/tasks/teardown.ts +++ b/plugins/heroku/src/tasks/teardown.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { readState } from '@dotcom-tool-kit/state' import { styles } from '@dotcom-tool-kit/logger' import { scaleDyno } from '../scaleDyno' diff --git a/plugins/heroku/tsconfig.json b/plugins/heroku/tsconfig.json index 8fb2c32eb..0a6805af7 100644 --- a/plugins/heroku/tsconfig.json +++ b/plugins/heroku/tsconfig.json @@ -20,7 +20,7 @@ "path": "../npm" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/logger" @@ -36,5 +36,7 @@ "outDir": "lib", "rootDir": "src" }, - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/jest/package.json b/plugins/jest/package.json index 4bc9d51fd..e70c10f33 100644 --- a/plugins/jest/package.json +++ b/plugins/jest/package.json @@ -10,8 +10,8 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "tslib": "^2.3.1" }, "peerDependencies": { diff --git a/plugins/jest/src/tasks/ci.ts b/plugins/jest/src/tasks/ci.ts index eec26367e..1ed1044e8 100644 --- a/plugins/jest/src/tasks/ci.ts +++ b/plugins/jest/src/tasks/ci.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { JestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/jest' import runJest from '../run-jest' diff --git a/plugins/jest/src/tasks/local.ts b/plugins/jest/src/tasks/local.ts index ed8585124..8ecd8f470 100644 --- a/plugins/jest/src/tasks/local.ts +++ b/plugins/jest/src/tasks/local.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { JestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/jest' import runJest from '../run-jest' diff --git a/plugins/jest/tsconfig.json b/plugins/jest/tsconfig.json index c6b10435b..29c8073d9 100644 --- a/plugins/jest/tsconfig.json +++ b/plugins/jest/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/logger" @@ -15,5 +15,7 @@ "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/lint-staged/package.json b/plugins/lint-staged/package.json index a6be1f57d..d47e4365f 100644 --- a/plugins/lint-staged/package.json +++ b/plugins/lint-staged/package.json @@ -10,9 +10,9 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/package-json-hook": "^4.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "lint-staged": "^11.2.3", "tslib": "^2.3.1" }, diff --git a/plugins/lint-staged/src/tasks/lint-staged.ts b/plugins/lint-staged/src/tasks/lint-staged.ts index e721560c5..281e439a7 100644 --- a/plugins/lint-staged/src/tasks/lint-staged.ts +++ b/plugins/lint-staged/src/tasks/lint-staged.ts @@ -1,6 +1,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookConsole } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import lintStaged from 'lint-staged' export default class LintStaged extends Task { diff --git a/plugins/mocha/package.json b/plugins/mocha/package.json index a60c6b37b..e5b43fce5 100644 --- a/plugins/mocha/package.json +++ b/plugins/mocha/package.json @@ -10,9 +10,9 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "glob": "^7.1.7", "tslib": "^2.3.1" }, diff --git a/plugins/mocha/src/tasks/mocha.ts b/plugins/mocha/src/tasks/mocha.ts index 7e7658c7c..1eeb46709 100644 --- a/plugins/mocha/src/tasks/mocha.ts +++ b/plugins/mocha/src/tasks/mocha.ts @@ -1,5 +1,5 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { glob } from 'glob' import { MochaSchema } from '@dotcom-tool-kit/schemas/lib/plugins/mocha' import { fork } from 'child_process' diff --git a/plugins/mocha/tsconfig.json b/plugins/mocha/tsconfig.json index 0d3f57ede..8beb1c2e5 100644 --- a/plugins/mocha/tsconfig.json +++ b/plugins/mocha/tsconfig.json @@ -5,16 +5,21 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/schemas" } ], - "include": ["src/**/*"], + "include": [ + "src/**/*" + ], "compilerOptions": { "outDir": "lib", "rootDir": "src", - "types": ["node", "mocha"] + "types": [ + "node", + "mocha" + ] } } diff --git a/plugins/n-test/package.json b/plugins/n-test/package.json index 41a8abd3b..76ff7552d 100644 --- a/plugins/n-test/package.json +++ b/plugins/n-test/package.json @@ -10,9 +10,9 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "@financial-times/n-test": "^6.1.0-beta.1", "tslib": "^2.3.1" }, diff --git a/plugins/n-test/src/tasks/n-test.ts b/plugins/n-test/src/tasks/n-test.ts index 74789068d..70dfd6950 100644 --- a/plugins/n-test/src/tasks/n-test.ts +++ b/plugins/n-test/src/tasks/n-test.ts @@ -1,5 +1,5 @@ import { styles } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { SmokeTestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/n-test' import { SmokeTest } from '@financial-times/n-test' import { readState } from '@dotcom-tool-kit/state' diff --git a/plugins/n-test/tsconfig.json b/plugins/n-test/tsconfig.json index 6d8f90bbf..392329b3c 100644 --- a/plugins/n-test/tsconfig.json +++ b/plugins/n-test/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.settings.json", - "include": ["src/**/*"], + "include": [ + "src/**/*" + ], "compilerOptions": { "outDir": "lib", "rootDir": "src" @@ -13,7 +15,7 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/schemas" diff --git a/plugins/next-router/package.json b/plugins/next-router/package.json index 3b3fbdf08..10f89a867 100644 --- a/plugins/next-router/package.json +++ b/plugins/next-router/package.json @@ -10,11 +10,11 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", + "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", - "@dotcom-tool-kit/state": "^3.3.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", - "@dotcom-tool-kit/doppler": "^1.1.0", + "@dotcom-tool-kit/state": "^3.3.0", "ft-next-router": "^3.0.0", "tslib": "^2.3.1" }, diff --git a/plugins/next-router/src/tasks/next-router.ts b/plugins/next-router/src/tasks/next-router.ts index d227a3b49..bbeaf711a 100644 --- a/plugins/next-router/src/tasks/next-router.ts +++ b/plugins/next-router/src/tasks/next-router.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { register } from 'ft-next-router' import { readState } from '@dotcom-tool-kit/state' diff --git a/plugins/next-router/tsconfig.json b/plugins/next-router/tsconfig.json index 3cb96252e..e77e250c9 100644 --- a/plugins/next-router/tsconfig.json +++ b/plugins/next-router/tsconfig.json @@ -15,7 +15,7 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/doppler" @@ -24,5 +24,7 @@ "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/node/package.json b/plugins/node/package.json index ef5d10165..59649230c 100644 --- a/plugins/node/package.json +++ b/plugins/node/package.json @@ -10,9 +10,9 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "@dotcom-tool-kit/doppler": "^1.1.0", "get-port": "^5.1.1", "tslib": "^2.3.1", diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index aae2fc18f..2931dc794 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -1,7 +1,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookConsole, hookFork, styles } from '@dotcom-tool-kit/logger' import { writeState } from '@dotcom-tool-kit/state' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { NodeSchema } from '@dotcom-tool-kit/schemas/lib/plugins/node' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { fork } from 'child_process' diff --git a/plugins/node/tsconfig.json b/plugins/node/tsconfig.json index 62e84d6ff..be559dc10 100644 --- a/plugins/node/tsconfig.json +++ b/plugins/node/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/error" @@ -24,5 +24,7 @@ "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/nodemon/package.json b/plugins/nodemon/package.json index b899b9edc..e29fb9c04 100644 --- a/plugins/nodemon/package.json +++ b/plugins/nodemon/package.json @@ -10,9 +10,9 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "@dotcom-tool-kit/doppler": "^1.1.0", "get-port": "^5.1.1", "tslib": "^2.3.1" diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index 5a731efa6..b805c8c98 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -1,5 +1,5 @@ import { hookFork } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { NodemonSchema } from '@dotcom-tool-kit/schemas/lib/plugins/nodemon' import { writeState } from '@dotcom-tool-kit/state' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' diff --git a/plugins/nodemon/tsconfig.json b/plugins/nodemon/tsconfig.json index 21f58ad35..03b725021 100644 --- a/plugins/nodemon/tsconfig.json +++ b/plugins/nodemon/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/error" @@ -24,5 +24,7 @@ "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/npm/package.json b/plugins/npm/package.json index 54124b43f..de634eb59 100644 --- a/plugins/npm/package.json +++ b/plugins/npm/package.json @@ -11,10 +11,10 @@ "license": "ISC", "dependencies": { "@actions/exec": "^1.1.0", + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "libnpmpack": "^3.1.0", "libnpmpublish": "^5.0.1", "pacote": "^12.0.3", diff --git a/plugins/npm/src/tasks/prune.ts b/plugins/npm/src/tasks/prune.ts index 03a29de19..46cb52a47 100644 --- a/plugins/npm/src/tasks/prune.ts +++ b/plugins/npm/src/tasks/prune.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ToolKitError } from '@dotcom-tool-kit/error' import * as exec from '@actions/exec' diff --git a/plugins/npm/src/tasks/publish.ts b/plugins/npm/src/tasks/publish.ts index ceadda8ac..3c33ed282 100644 --- a/plugins/npm/src/tasks/publish.ts +++ b/plugins/npm/src/tasks/publish.ts @@ -1,6 +1,6 @@ import { readFile, writeFile } from 'fs/promises' import { ToolKitError } from '@dotcom-tool-kit/error' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import pacote from 'pacote' import { readState } from '@dotcom-tool-kit/state' import pack from 'libnpmpack' diff --git a/plugins/npm/tsconfig.json b/plugins/npm/tsconfig.json index f46d28df8..2a922e8f9 100644 --- a/plugins/npm/tsconfig.json +++ b/plugins/npm/tsconfig.json @@ -12,11 +12,13 @@ "path": "../../plugins/package-json-hook" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/state" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/pa11y/package.json b/plugins/pa11y/package.json index 63834219d..720191d2d 100644 --- a/plugins/pa11y/package.json +++ b/plugins/pa11y/package.json @@ -12,7 +12,7 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/base": "^3.4.1", "pa11y-ci": "^3.0.1", "tslib": "^2.3.1" }, diff --git a/plugins/pa11y/src/tasks/pa11y.ts b/plugins/pa11y/src/tasks/pa11y.ts index f379f1282..4d9f66962 100644 --- a/plugins/pa11y/src/tasks/pa11y.ts +++ b/plugins/pa11y/src/tasks/pa11y.ts @@ -1,5 +1,5 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import type { Pa11ySchema } from '@dotcom-tool-kit/schemas/lib/plugins/pa11y' import { fork } from 'child_process' import { readState } from '@dotcom-tool-kit/state' diff --git a/plugins/pa11y/tsconfig.json b/plugins/pa11y/tsconfig.json index 13661dc57..6f290624f 100644 --- a/plugins/pa11y/tsconfig.json +++ b/plugins/pa11y/tsconfig.json @@ -3,11 +3,14 @@ "compilerOptions": { "outDir": "lib", "rootDir": "src", - "lib": ["ES2019", "DOM"] + "lib": [ + "ES2019", + "DOM" + ] }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/logger" @@ -19,5 +22,7 @@ "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/package-json-hook/package.json b/plugins/package-json-hook/package.json index 119de1e4a..3dbc8a490 100644 --- a/plugins/package-json-hook/package.json +++ b/plugins/package-json-hook/package.json @@ -10,8 +10,8 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/conflict": "^1.0.0", - "@dotcom-tool-kit/types": "^3.4.0", "@financial-times/package-json": "^3.0.0", "lodash": "^4.17.21", "tslib": "^2.3.1" diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index 59a10fac6..b6c9686e6 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -1,5 +1,5 @@ import type { z } from 'zod' -import { Hook, HookInstallation, Plugin } from '@dotcom-tool-kit/types' +import { Hook, HookInstallation, Plugin } from '@dotcom-tool-kit/base' import fs from 'fs' import get from 'lodash/get' import set from 'lodash/set' diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 3e3616db0..322d198e0 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -3,7 +3,7 @@ import * as path from 'path' import { promises as fs } from 'fs' import PackageJson from '../src/package-json-helper' import winston, { Logger } from 'winston' -import { HookInstallation } from '@dotcom-tool-kit/types' +import { HookInstallation } from '@dotcom-tool-kit/base' import { PackageJsonSchema } from '@dotcom-tool-kit/schemas/lib/hooks/package-json' const logger = (winston as unknown) as Logger diff --git a/plugins/package-json-hook/tsconfig.json b/plugins/package-json-hook/tsconfig.json index c7091d69d..093ffa39a 100644 --- a/plugins/package-json-hook/tsconfig.json +++ b/plugins/package-json-hook/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/schemas" diff --git a/plugins/prettier/package.json b/plugins/prettier/package.json index 291f6a295..e151fa631 100644 --- a/plugins/prettier/package.json +++ b/plugins/prettier/package.json @@ -10,10 +10,10 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/package-json-hook": "^4.2.0", - "@dotcom-tool-kit/types": "^3.6.0", "fast-glob": "^3.2.7", "hook-std": "^2.0.0", "prettier": "^2.2.1", diff --git a/plugins/prettier/src/tasks/prettier.ts b/plugins/prettier/src/tasks/prettier.ts index 9af301b0b..4aa3779e5 100644 --- a/plugins/prettier/src/tasks/prettier.ts +++ b/plugins/prettier/src/tasks/prettier.ts @@ -3,7 +3,7 @@ import { PrettierOptions, PrettierSchema } from '@dotcom-tool-kit/schemas/lib/pl import { promises as fsp } from 'fs' import fg from 'fast-glob' import { hookConsole, styles } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ToolKitError } from '@dotcom-tool-kit/error' export default class Prettier extends Task { diff --git a/plugins/prettier/tsconfig.json b/plugins/prettier/tsconfig.json index 2a4381f2e..47e6db56d 100644 --- a/plugins/prettier/tsconfig.json +++ b/plugins/prettier/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.settings.json", - "include": ["src/**/*"], + "include": [ + "src/**/*" + ], "compilerOptions": { "outDir": "lib", "rootDir": "src" @@ -16,7 +18,7 @@ "path": "../../lib/schemas" }, { - "path": "../../lib/types" + "path": "../../lib/base" } ] } diff --git a/plugins/serverless/package.json b/plugins/serverless/package.json index 62d78ba6c..6ae03c4fe 100644 --- a/plugins/serverless/package.json +++ b/plugins/serverless/package.json @@ -25,11 +25,11 @@ "serverless-offline": "^12.0.4" }, "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/state": "^3.3.0", - "@dotcom-tool-kit/types": "^3.6.0", "get-port": "^5.1.1", "tslib": "^2.3.1", "wait-port": "^0.2.9" diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index 2b8ed4df5..4f982dfae 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -1,6 +1,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { getOptions } from '@dotcom-tool-kit/options' diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index df668e339..c0f8ff34a 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -1,6 +1,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { spawn } from 'child_process' diff --git a/plugins/serverless/src/tasks/run.ts b/plugins/serverless/src/tasks/run.ts index 54287dbd9..9dc5ebc20 100644 --- a/plugins/serverless/src/tasks/run.ts +++ b/plugins/serverless/src/tasks/run.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { spawn } from 'child_process' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' diff --git a/plugins/serverless/src/tasks/teardown.ts b/plugins/serverless/src/tasks/teardown.ts index 1e9664f25..00b3a8676 100644 --- a/plugins/serverless/src/tasks/teardown.ts +++ b/plugins/serverless/src/tasks/teardown.ts @@ -1,6 +1,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { readState } from '@dotcom-tool-kit/state' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' diff --git a/plugins/serverless/tsconfig.json b/plugins/serverless/tsconfig.json index ab5835566..49eaf3274 100644 --- a/plugins/serverless/tsconfig.json +++ b/plugins/serverless/tsconfig.json @@ -6,7 +6,7 @@ }, "references": [ { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/doppler" @@ -21,5 +21,7 @@ "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/typescript/package.json b/plugins/typescript/package.json index 6a26d9b90..1a2155e42 100644 --- a/plugins/typescript/package.json +++ b/plugins/typescript/package.json @@ -25,8 +25,8 @@ "typescript": "3.x || 4.x" }, "dependencies": { - "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0" + "@dotcom-tool-kit/base": "^3.4.1", + "@dotcom-tool-kit/logger": "^3.4.0" }, "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0", diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index d79d11c78..64eca6cc3 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -1,5 +1,5 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import type { TypeScriptSchema } from '@dotcom-tool-kit/schemas/lib/plugins/typescript' import { fork } from 'child_process' diff --git a/plugins/typescript/tsconfig.json b/plugins/typescript/tsconfig.json index beea17c63..c8906d23a 100644 --- a/plugins/typescript/tsconfig.json +++ b/plugins/typescript/tsconfig.json @@ -9,11 +9,13 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/upload-assets-to-s3/package.json b/plugins/upload-assets-to-s3/package.json index 263af8603..a12f6f876 100644 --- a/plugins/upload-assets-to-s3/package.json +++ b/plugins/upload-assets-to-s3/package.json @@ -11,9 +11,9 @@ "license": "ISC", "dependencies": { "@aws-sdk/client-s3": "^3.256.0", + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "glob": "^7.1.6", "mime": "^2.5.2", "tslib": "^2.3.1" diff --git a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts index ddb856741..5e687e360 100644 --- a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts +++ b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import * as fs from 'fs' import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3' import path from 'path' diff --git a/plugins/upload-assets-to-s3/tsconfig.json b/plugins/upload-assets-to-s3/tsconfig.json index c562891b1..1b8e043f8 100644 --- a/plugins/upload-assets-to-s3/tsconfig.json +++ b/plugins/upload-assets-to-s3/tsconfig.json @@ -12,11 +12,13 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/schemas" } ], - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } diff --git a/plugins/webpack/package.json b/plugins/webpack/package.json index 20e2bb0df..7851571b3 100644 --- a/plugins/webpack/package.json +++ b/plugins/webpack/package.json @@ -17,9 +17,9 @@ "test": "cd ../../ ; npx jest --silent --projects plugins/webpack" }, "dependencies": { + "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/types": "^3.6.0", "webpack-cli": "^4.6.0", "tslib": "^2.3.1" }, diff --git a/plugins/webpack/src/tasks/development.ts b/plugins/webpack/src/tasks/development.ts index 3574a5588..fd8b1cecc 100644 --- a/plugins/webpack/src/tasks/development.ts +++ b/plugins/webpack/src/tasks/development.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' diff --git a/plugins/webpack/src/tasks/production.ts b/plugins/webpack/src/tasks/production.ts index c4cce6a46..151465cf7 100644 --- a/plugins/webpack/src/tasks/production.ts +++ b/plugins/webpack/src/tasks/production.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' diff --git a/plugins/webpack/src/tasks/watch.ts b/plugins/webpack/src/tasks/watch.ts index 99921e1e8..97c6675ab 100644 --- a/plugins/webpack/src/tasks/watch.ts +++ b/plugins/webpack/src/tasks/watch.ts @@ -1,4 +1,4 @@ -import { Task } from '@dotcom-tool-kit/types' +import { Task } from '@dotcom-tool-kit/base' import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' diff --git a/plugins/webpack/tsconfig.json b/plugins/webpack/tsconfig.json index 61644460f..e868bd289 100644 --- a/plugins/webpack/tsconfig.json +++ b/plugins/webpack/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.settings.json", - "include": ["src/**/*"], + "include": [ + "src/**/*" + ], "compilerOptions": { "outDir": "lib", "rootDir": "src" @@ -10,7 +12,7 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/base" }, { "path": "../../lib/schemas" From ee5839b7ac6a9fc8321beb8a7503f624aabf15b7 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 5 Jan 2024 13:10:41 +0000 Subject: [PATCH 094/321] feat: split remaining bits of types into config and plugins packages --- core/cli/package.json | 3 +- core/cli/src/config.ts | 2 +- core/cli/src/config/validate-plugins.ts | 4 +- core/cli/src/plugin.ts | 2 +- core/cli/src/plugin/entry-point.ts | 3 +- core/cli/src/plugin/is-descendent.ts | 2 +- core/cli/src/plugin/merge-commands.ts | 5 +- core/cli/src/plugin/merge-hooks.ts | 3 +- core/cli/src/plugin/merge-inits.ts | 3 +- core/cli/src/plugin/merge-options.ts | 5 +- core/cli/src/plugin/merge-tasks.ts | 3 +- core/cli/src/plugin/options.ts | 2 +- core/cli/src/plugin/reduce-installations.ts | 10 +- core/cli/src/rc-file.ts | 2 +- core/cli/test/index.test.ts | 6 +- core/create/package.json | 3 +- core/create/src/index.ts | 2 +- core/create/src/prompts/conflicts.ts | 3 +- core/create/src/prompts/oidc.ts | 2 +- core/create/src/prompts/options.ts | 3 +- lib/base/src/base.ts | 4 +- lib/base/src/symbols.ts | 5 +- lib/config/package.json | 18 ++ lib/config/src/index.ts | 34 +++ lib/doppler/package.json | 1 - lib/plugin/package.json | 13 + lib/plugin/src/index.ts | 34 +++ lib/{types => schemas}/README.md | 2 + lib/types/CHANGELOG.md | 307 -------------------- lib/types/jest.config.js | 5 - lib/types/package.json | 48 --- lib/types/src/index.ts | 70 ----- lib/types/tsconfig.json | 24 -- lib/vault/package.json | 1 - package-lock.json | 51 ++-- plugins/circleci-npm/package.json | 1 - 36 files changed, 176 insertions(+), 510 deletions(-) create mode 100644 lib/config/package.json create mode 100644 lib/config/src/index.ts create mode 100644 lib/plugin/package.json create mode 100644 lib/plugin/src/index.ts rename lib/{types => schemas}/README.md (97%) delete mode 100644 lib/types/CHANGELOG.md delete mode 100644 lib/types/jest.config.js delete mode 100644 lib/types/package.json delete mode 100644 lib/types/src/index.ts delete mode 100644 lib/types/tsconfig.json diff --git a/core/cli/package.json b/core/cli/package.json index cc6021ed7..5dfebffdb 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -42,11 +42,12 @@ }, "dependencies": { "@dotcom-tool-kit/base": "^3.4.1", + "@dotcom-tool-kit/config": "^1.0.0", "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/options": "^3.2.0", - "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/plugin": "^1.0.0", "@dotcom-tool-kit/validated": "^1.0.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "cosmiconfig": "^7.0.0", diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 785b8b61b..d4883282c 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -9,7 +9,7 @@ import { findConflictingEntries } from '@dotcom-tool-kit/conflict' import { ToolKitConflictError } from '@dotcom-tool-kit/error' -import { RawConfig, ValidConfig, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { RawConfig, ValidConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' import { formatTaskConflicts, formatUndefinedCommandTasks, diff --git a/core/cli/src/config/validate-plugins.ts b/core/cli/src/config/validate-plugins.ts index ebfe13ef4..7b3661627 100644 --- a/core/cli/src/config/validate-plugins.ts +++ b/core/cli/src/config/validate-plugins.ts @@ -1,5 +1,5 @@ -import { RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/types' -import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' +import type { RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' +import { type Validated, reduceValidated } from '@dotcom-tool-kit/validated' export function validatePlugins(config: RawConfig): Validated { const validatedPlugins = reduceValidated( diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index a8bd37462..f54bb2539 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,5 +1,5 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import { Plugin, RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { Plugin, RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' import { invalid, reduceValidated, valid, Validated } from '@dotcom-tool-kit/validated' import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' diff --git a/core/cli/src/plugin/entry-point.ts b/core/cli/src/plugin/entry-point.ts index 6413fc8fd..13a3f05ca 100644 --- a/core/cli/src/plugin/entry-point.ts +++ b/core/cli/src/plugin/entry-point.ts @@ -1,6 +1,7 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import { Base, EntryPoint } from '@dotcom-tool-kit/types' +import type { Base } from '@dotcom-tool-kit/base' +import type {EntryPoint} from '@dotcom-tool-kit/plugin' import { Validated, invalid } from '@dotcom-tool-kit/validated' import resolvePkg from 'resolve-pkg' import { isPlainObject } from 'lodash' diff --git a/core/cli/src/plugin/is-descendent.ts b/core/cli/src/plugin/is-descendent.ts index ac16ef99e..798746648 100644 --- a/core/cli/src/plugin/is-descendent.ts +++ b/core/cli/src/plugin/is-descendent.ts @@ -1,4 +1,4 @@ -import { Plugin } from '@dotcom-tool-kit/types' +import type { Plugin } from '@dotcom-tool-kit/plugin' export function isDescendent(possibleAncestor: Plugin, possibleDescendent: Plugin): boolean { if (!possibleDescendent.parent) { diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts index 55eeef745..bb7eb7727 100644 --- a/core/cli/src/plugin/merge-commands.ts +++ b/core/cli/src/plugin/merge-commands.ts @@ -1,5 +1,6 @@ -import { CommandTask, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' -import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' +import type { CommandTask, Plugin } from '@dotcom-tool-kit/plugin' +import type {ValidPluginsConfig} from '@dotcom-tool-kit/config' +import { type Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { isDescendent } from './is-descendent' export const mergePluginCommands = (config: ValidPluginsConfig, plugin: Plugin) => { diff --git a/core/cli/src/plugin/merge-hooks.ts b/core/cli/src/plugin/merge-hooks.ts index cc06d16e3..2cfb5e774 100644 --- a/core/cli/src/plugin/merge-hooks.ts +++ b/core/cli/src/plugin/merge-hooks.ts @@ -1,4 +1,5 @@ -import { EntryPoint, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import type { EntryPoint, Plugin } from '@dotcom-tool-kit/plugin' +import type {ValidPluginsConfig} from '@dotcom-tool-kit/config' import { isConflict } from '@dotcom-tool-kit/conflict' export const mergePluginHooks = (config: ValidPluginsConfig, plugin: Plugin) => { diff --git a/core/cli/src/plugin/merge-inits.ts b/core/cli/src/plugin/merge-inits.ts index 7baf44dbe..eeab89324 100644 --- a/core/cli/src/plugin/merge-inits.ts +++ b/core/cli/src/plugin/merge-inits.ts @@ -1,4 +1,5 @@ -import { Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import type { Plugin } from '@dotcom-tool-kit/plugin' +import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' export const mergePluginInits = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { diff --git a/core/cli/src/plugin/merge-options.ts b/core/cli/src/plugin/merge-options.ts index 60f72f876..6c1becbbd 100644 --- a/core/cli/src/plugin/merge-options.ts +++ b/core/cli/src/plugin/merge-options.ts @@ -1,6 +1,7 @@ -import { Plugin, PluginOptions, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import type { Plugin, PluginOptions} from '@dotcom-tool-kit/plugin' +import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isDescendent } from './is-descendent' -import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' +import { type Conflict, isConflict } from '@dotcom-tool-kit/conflict' // merge options from this plugin's config with any options we've collected already // TODO this is almost the exact same code as for command tasks, refactor diff --git a/core/cli/src/plugin/merge-tasks.ts b/core/cli/src/plugin/merge-tasks.ts index 1dd97cad8..013a21a10 100644 --- a/core/cli/src/plugin/merge-tasks.ts +++ b/core/cli/src/plugin/merge-tasks.ts @@ -1,4 +1,5 @@ -import { EntryPoint, Plugin, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import type{ EntryPoint, Plugin } from '@dotcom-tool-kit/plugin' +import type {ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isConflict } from '@dotcom-tool-kit/conflict' // add plugin tasks to our task registry, handling any conflicts diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index d971409e6..77f44fe52 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -1,4 +1,4 @@ -import { ValidPluginsConfig } from '@dotcom-tool-kit/types' +import { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { InvalidOption } from '../messages' import { SchemaOptions, PluginSchemas } from '@dotcom-tool-kit/schemas' import { isConflict } from '@dotcom-tool-kit/conflict' diff --git a/core/cli/src/plugin/reduce-installations.ts b/core/cli/src/plugin/reduce-installations.ts index 5a310aa85..75d74bc02 100644 --- a/core/cli/src/plugin/reduce-installations.ts +++ b/core/cli/src/plugin/reduce-installations.ts @@ -1,8 +1,10 @@ -import { Logger } from 'winston' -import { HookClass, HookInstallation, Plugin, ValidConfig } from '@dotcom-tool-kit/types' -import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' +import type { Logger } from 'winston' +import type { HookClass, HookInstallation } from '@dotcom-tool-kit/base' +import type { Plugin} from '@dotcom-tool-kit/plugin' +import type { ValidConfig} from '@dotcom-tool-kit/config' +import type { HookSchemas, HookOptions } from '@dotcom-tool-kit/schemas' +import { type Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { groupBy } from 'lodash' -import { HookSchemas, HookOptions } from '@dotcom-tool-kit/schemas' // this function recursively collects all the hook installation requests from all plugins, // and merges them into a single, flat array of HookInstallation objects and/or Conflicts. diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index b2c75b420..de5319a46 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -1,5 +1,5 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import { RCFile } from '@dotcom-tool-kit/types/src' +import type { RCFile } from '@dotcom-tool-kit/plugin' import { cosmiconfig } from 'cosmiconfig' import * as path from 'path' import type { Logger } from 'winston' diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index d5b6c2186..9929791e1 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -1,8 +1,10 @@ import { ToolKitError } from '@dotcom-tool-kit/error' -import { Plugin, Valid, ValidPluginsConfig } from '@dotcom-tool-kit/types' +import type { Valid } from '@dotcom-tool-kit/validated' +import type { Plugin } from '@dotcom-tool-kit/plugin' +import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { describe, expect, it, jest } from '@jest/globals' import * as path from 'path' -import winston, { Logger } from 'winston' +import winston, { type Logger } from 'winston' import { createConfig, validateConfig } from '../src/config' import { loadPlugin, resolvePlugin } from '../src/plugin' import { validatePlugins } from '../src/config/validate-plugins' diff --git a/core/create/package.json b/core/create/package.json index b485b1645..8b6004683 100644 --- a/core/create/package.json +++ b/core/create/package.json @@ -17,7 +17,8 @@ "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/schemas": "^1.0.0", - "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/plugin": "^1.0.0", + "@dotcom-tool-kit/schemas": "^1.0.0", "@octokit/rest": "^19.0.5", "@quarterto/parse-makefile-rules": "^1.1.0", "cli-highlight": "^2.1.11", diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 5669af864..2802960d2 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -1,6 +1,6 @@ import * as ToolkitErrorModule from '@dotcom-tool-kit/error' import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' -import type { RCFile } from '@dotcom-tool-kit/types' +import type { RCFile } from '@dotcom-tool-kit/plugin' import { exec as _exec } from 'child_process' import type { cosmiconfig } from 'cosmiconfig' import type { loadConfig as loadConfigType } from 'dotcom-tool-kit/lib/config' diff --git a/core/create/src/prompts/conflicts.ts b/core/create/src/prompts/conflicts.ts index c4137f310..cc254593b 100644 --- a/core/create/src/prompts/conflicts.ts +++ b/core/create/src/prompts/conflicts.ts @@ -1,6 +1,7 @@ import * as ToolkitErrorModule from '@dotcom-tool-kit/error' import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' -import type { RCFile, ValidConfig } from '@dotcom-tool-kit/types' +import type { RCFile} from '@dotcom-tool-kit/plugin' +import type { ValidConfig } from '@dotcom-tool-kit/config' import type installHooksType from 'dotcom-tool-kit/lib/install' import { promises as fs } from 'fs' import importCwd from 'import-cwd' diff --git a/core/create/src/prompts/oidc.ts b/core/create/src/prompts/oidc.ts index 2e7704251..30423c343 100644 --- a/core/create/src/prompts/oidc.ts +++ b/core/create/src/prompts/oidc.ts @@ -4,7 +4,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { setOptions } from '@dotcom-tool-kit/options' -import type { RCFile } from '@dotcom-tool-kit/types' +import type { RCFile } from '@dotcom-tool-kit/plugin' import { Octokit } from '@octokit/rest' import * as suggester from 'code-suggester' import { highlight } from 'cli-highlight' diff --git a/core/create/src/prompts/options.ts b/core/create/src/prompts/options.ts index 99367508f..4dd054840 100644 --- a/core/create/src/prompts/options.ts +++ b/core/create/src/prompts/options.ts @@ -1,5 +1,6 @@ import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' -import type { RCFile, RawConfig } from '@dotcom-tool-kit/types' +import type { RCFile } from '@dotcom-tool-kit/plugin' +import type { RawConfig } from '@dotcom-tool-kit/config' import type { PromptGenerators } from '@dotcom-tool-kit/schemas' import { promises as fs } from 'fs' import YAML from 'yaml' diff --git a/lib/base/src/base.ts b/lib/base/src/base.ts index 6d4930f1e..8ca425c9a 100644 --- a/lib/base/src/base.ts +++ b/lib/base/src/base.ts @@ -30,7 +30,7 @@ export abstract class Base { if (!this.is(objectToCheck)) { return invalid([ `${s.plugin( - '@dotcom-tool-kit/types' + '@dotcom-tool-kit/base' )} type symbol is missing, make sure that this object derives from the ${s.code('Task')} or ${s.code( 'Hook' )} class defined by the plugin` @@ -38,7 +38,7 @@ export abstract class Base { } // an 'objectToCheck' from a plugin is compatible with this CLI if its - // version is semver-compatible with the @dotcom-tool-kit/types included by + // version is semver-compatible with the @dotcom-tool-kit/base included by // the CLI (which is what's calling this). so, prepend ^ to our version, // and check our version satisfies that. diff --git a/lib/base/src/symbols.ts b/lib/base/src/symbols.ts index 79ba26163..f62c75247 100644 --- a/lib/base/src/symbols.ts +++ b/lib/base/src/symbols.ts @@ -1,5 +1,8 @@ // uses Symbol.for, not Symbol, so that they're compatible across different -// @dotcom-tool-kit/types instances +// @dotcom-tool-kit/base instances + +// TODO these symbols say '@dotcom-tool-kit/types' because they used to live +// in that package. changing that would be a backwards compatibility nightmare // used as the name for the property we use to identify classes export const typeSymbol = Symbol.for('@dotcom-tool-kit/types') diff --git a/lib/config/package.json b/lib/config/package.json new file mode 100644 index 000000000..1cbb5aaff --- /dev/null +++ b/lib/config/package.json @@ -0,0 +1,18 @@ +{ + "name": "@dotcom-tool-kit/config", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", + "@dotcom-tool-kit/plugin": "^1.0.0", + "@dotcom-tool-kit/schemas": "^1.0.0", + "@dotcom-tool-kit/validated": "^1.0.0" + } +} diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts new file mode 100644 index 000000000..6cc39dc14 --- /dev/null +++ b/lib/config/src/index.ts @@ -0,0 +1,34 @@ +export type RCFile = { + plugins: string[] + installs: { [id: string]: string } + tasks: { [id: string]: string } + commands: { [id: string]: string | string[] } + options: { [id: string]: Record } + hooks: { [id: string]: Record }[] + init: string[] + } + + export interface Plugin { + id: string + root: string + rcFile?: RCFile + parent?: Plugin + children?: Plugin[] + } + + export interface CommandTask { + id: string + plugin: Plugin + tasks: string[] + } + + export interface PluginOptions { + options: Record + plugin: Plugin + forPlugin: Plugin + } + + export interface EntryPoint { + plugin: Plugin + modulePath: string + } diff --git a/lib/doppler/package.json b/lib/doppler/package.json index e3c781833..9f4f7415e 100644 --- a/lib/doppler/package.json +++ b/lib/doppler/package.json @@ -10,7 +10,6 @@ "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/options": "^3.2.0", - "@dotcom-tool-kit/types": "^3.6.0", "@dotcom-tool-kit/vault": "^3.2.0", "tslib": "^2.3.1" }, diff --git a/lib/plugin/package.json b/lib/plugin/package.json new file mode 100644 index 000000000..be96e14a6 --- /dev/null +++ b/lib/plugin/package.json @@ -0,0 +1,13 @@ +{ + "name": "@dotcom-tool-kit/plugin", + "version": "1.0.0", + "description": "", + "main": "index.js", + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts new file mode 100644 index 000000000..6cc39dc14 --- /dev/null +++ b/lib/plugin/src/index.ts @@ -0,0 +1,34 @@ +export type RCFile = { + plugins: string[] + installs: { [id: string]: string } + tasks: { [id: string]: string } + commands: { [id: string]: string | string[] } + options: { [id: string]: Record } + hooks: { [id: string]: Record }[] + init: string[] + } + + export interface Plugin { + id: string + root: string + rcFile?: RCFile + parent?: Plugin + children?: Plugin[] + } + + export interface CommandTask { + id: string + plugin: Plugin + tasks: string[] + } + + export interface PluginOptions { + options: Record + plugin: Plugin + forPlugin: Plugin + } + + export interface EntryPoint { + plugin: Plugin + modulePath: string + } diff --git a/lib/types/README.md b/lib/schemas/README.md similarity index 97% rename from lib/types/README.md rename to lib/schemas/README.md index 42ff55ddb..f184863ee 100644 --- a/lib/types/README.md +++ b/lib/schemas/README.md @@ -1,5 +1,7 @@ # Tool Kit Option Schemas +> ⚠️ this README is out of date and describes the pre-Zod schema types. update plz + ## Overview Tool Kit allows plugins to take options from a `.toolkitrc.yml` file. Each diff --git a/lib/types/CHANGELOG.md b/lib/types/CHANGELOG.md deleted file mode 100644 index 4ce737819..000000000 --- a/lib/types/CHANGELOG.md +++ /dev/null @@ -1,307 +0,0 @@ -# Changelog - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/logger bumped from ^2.1.0 to ^2.1.1 - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/logger bumped from ^2.1.1 to ^2.2.0 - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/logger bumped from ^3.2.0 to ^3.3.0 - -## [3.6.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v3.5.0...types-v3.6.0) (2024-01-11) - - -### Features - -* add support for Node v20 ([759ac10](https://github.com/Financial-Times/dotcom-tool-kit/commit/759ac10e309885e99f54ae431c301c32ee04f972)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/error bumped from ^3.1.0 to ^3.2.0 - * @dotcom-tool-kit/logger bumped from ^3.3.1 to ^3.4.0 - -## [3.5.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v3.4.1...types-v3.5.0) (2023-12-18) - - -### Features - -* **create:** add suggestions to all required options ([2569e3f](https://github.com/Financial-Times/dotcom-tool-kit/commit/2569e3fdefc193298306844622f6238e74826084)) -* **create:** infer Heroku options based on Biz Ops and Heroku API ([8aa02b6](https://github.com/Financial-Times/dotcom-tool-kit/commit/8aa02b6916592abcdfbf3afa8c6c52e43dff83c5)) -* **create:** infer the rest of the Heroku options from Biz Ops data ([e3c626e](https://github.com/Financial-Times/dotcom-tool-kit/commit/e3c626ebfda662845d72c7130d197414fa922a91)) - - -### Bug Fixes - -* **create:** default all confirmation prompts to the happy path ([8dca215](https://github.com/Financial-Times/dotcom-tool-kit/commit/8dca2157ed42a39e36fb862641a7c6758c64db71)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/logger bumped from ^3.3.0 to ^3.3.1 - -## [3.4.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v3.3.1...types-v3.4.0) (2023-09-19) - - -### Features - -* **doppler:** add library to get secrets from doppler ([ce51a90](https://github.com/Financial-Times/dotcom-tool-kit/commit/ce51a904cdaffdf8e490e9cc09ad4a2ac14f255b)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/logger bumped from ^3.1.1 to ^3.2.0 - -## [3.3.1](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v3.3.0...types-v3.3.1) (2023-07-04) - - -### Bug Fixes - -* install Reliability Kit ESLint config and fix errors found ([35a6f77](https://github.com/Financial-Times/dotcom-tool-kit/commit/35a6f7754c33f58789b201594ed5d1000e029f1c)) - -## [3.3.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v3.2.0...types-v3.3.0) (2023-06-14) - - -### Features - -* disable Node 18's native fetch across all plugins ([ba10618](https://github.com/Financial-Times/dotcom-tool-kit/commit/ba10618f9eb861b8499255fcdb297502e7c42bdf)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/logger bumped from ^3.1.0 to ^3.1.1 - -## [3.2.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v3.1.0...types-v3.2.0) (2023-05-30) - - -### Features - -* **circleci:** add default value for CircleCI's node version option ([ab5ce94](https://github.com/Financial-Times/dotcom-tool-kit/commit/ab5ce94441983693d3849ee42cf0f1c30fcff67e)) -* **circleci:** add support for multiple Node versions ([10b15f4](https://github.com/Financial-Times/dotcom-tool-kit/commit/10b15f42f603c232293e15d05d4a062d7f855dbb)) - -## [3.1.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v3.0.0...types-v3.1.0) (2023-04-28) - - -### Features - -* **node:** disable native fetch in forked node processes ([73234e4](https://github.com/Financial-Times/dotcom-tool-kit/commit/73234e43d52a7dd02286c5a5b12e17766b7410bd)) -* **nodemon:** disable native fetch in forked node processes ([d946271](https://github.com/Financial-Times/dotcom-tool-kit/commit/d946271d80662812f017a6b2d897535dee9d2ddc)) -* specify Node 18 support in all packages' engines fields ([3b55c79](https://github.com/Financial-Times/dotcom-tool-kit/commit/3b55c79f3f55b448f1a92fcf842dab6a8906ea70)) - - -### Bug Fixes - -* **types:** make regex for determining release tags stricter ([3c85027](https://github.com/Financial-Times/dotcom-tool-kit/commit/3c8502786cfcac837ba3b301ee90a348753c5b41)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/error bumped from ^3.0.0 to ^3.1.0 - * @dotcom-tool-kit/logger bumped from ^3.0.0 to ^3.1.0 - -## [3.0.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.10.0...types-v3.0.0) (2023-04-18) - - -### ⚠ BREAKING CHANGES - -* drop support for Node 14 across all packages - -### Miscellaneous Chores - -* drop support for Node 14 across all packages ([aaee178](https://github.com/Financial-Times/dotcom-tool-kit/commit/aaee178b535a51f9c75a882d78ffd8e8aa3eac60)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/error bumped from ^2.0.0 to ^3.0.0 - * @dotcom-tool-kit/logger bumped from ^2.2.1 to ^3.0.0 - -## [2.10.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.9.2...types-v2.10.0) (2023-04-05) - - -### Features - -* **serverless:** add ServerlessDeploy task ([cd23f88](https://github.com/Financial-Times/dotcom-tool-kit/commit/cd23f88ce453a48dec393dc2645c7a22948e3944)) - -## [2.9.2](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.9.1...types-v2.9.2) (2023-03-22) - - -### Bug Fixes - -* **types:** make vault options optional ([f2e9cc0](https://github.com/Financial-Times/dotcom-tool-kit/commit/f2e9cc0b45d79c26c5ee5ec248fe44f073900835)) - -## [2.9.1](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.9.0...types-v2.9.1) (2023-03-15) - - -### Bug Fixes - -* **types:** allow files options to be simple strings as well as arrays ([3dc32c0](https://github.com/Financial-Times/dotcom-tool-kit/commit/3dc32c041849d8718861fbc0e0d3b72c026804c8)) - -## [2.9.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.8.0...types-v2.9.0) (2023-03-07) - - -### Features - -* add serverless plugin ([2041b7d](https://github.com/Financial-Times/dotcom-tool-kit/commit/2041b7d65c941823f59cbba61b11d32fe67ed906)) -* handle default option values with zod ([7c03517](https://github.com/Financial-Times/dotcom-tool-kit/commit/7c0351771cf1a3d795803295a41dfea755176b19)) -* **serverless:** define ServerlessProvision task ([6f49aaa](https://github.com/Financial-Times/dotcom-tool-kit/commit/6f49aaa80bb315e5dfd11068a21cb1d3e52ef36a)) -* **types:** use Zod for option schemas ([adc1643](https://github.com/Financial-Times/dotcom-tool-kit/commit/adc16437cf0977595b0d0c8b02337b78ee02b2b2)) -* validate plugin options with zod ([5164050](https://github.com/Financial-Times/dotcom-tool-kit/commit/5164050869958284611e0fa489551521201e6ac4)) - - -### Bug Fixes - -* **types:** allow arbitrary parameters to be passed to CircleCI jobs ([85cc8eb](https://github.com/Financial-Times/dotcom-tool-kit/commit/85cc8ebd9eafbe2de848dfe1c09bb320866910fb)) -* **types:** export jest and pa11y schemas that were previously missing ([11e7a1f](https://github.com/Financial-Times/dotcom-tool-kit/commit/11e7a1f30fccf7fc31c71c9867cab4f1754db34f)) -* **types:** make sure to export serverless schema type ([69584aa](https://github.com/Financial-Times/dotcom-tool-kit/commit/69584aa4f6f17172bda9714d0155a2517cba4121)) -* **types:** use more precise CircleCI configuration interface types ([2e4bf10](https://github.com/Financial-Times/dotcom-tool-kit/commit/2e4bf10157c3c321efd63b14aa5ebb1d38da9550)) -* **upload-assets-to-s3:** allow setting region for uploads ([89a984d](https://github.com/Financial-Times/dotcom-tool-kit/commit/89a984db001d6388eada79934d16bb9ad75c98e9)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/logger bumped from ^2.2.0 to ^2.2.1 - -## [2.8.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.7.1...types-v2.8.0) (2023-01-04) - - -### Features - -* **typescript:** add typescript plugin ([0421bdb](https://github.com/Financial-Times/dotcom-tool-kit/commit/0421bdba1f3a56fc8306b8c487433e54b740905c)) - -## [2.7.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.6.2...types-v2.7.0) (2022-12-08) - - -### Features - -* **circleci-heroku:** add support for using a Cypress docker image ([59f914a](https://github.com/Financial-Times/dotcom-tool-kit/commit/59f914aefdb7beae5e8ea0fac314efbc7194d802)) -* **circleci:** only print jobs that are missing in error ([c75c3ad](https://github.com/Financial-Times/dotcom-tool-kit/commit/c75c3ad6d91fbc5779d2a3fbed853f474babfad0)) -* **cli:** allow state to be shared between install hooks ([aaa5331](https://github.com/Financial-Times/dotcom-tool-kit/commit/aaa533123a48fe9168ec666edeabdd7a8c7428a6)) -* **cypress:** add plugin for running cypress locally and in the CI ([870a50b](https://github.com/Financial-Times/dotcom-tool-kit/commit/870a50b107bfa1f1846d35ba074fd3088cc63563)) - - -### Bug Fixes - -* **upload-assets-to-s3:** handle AWS keys correctly ([a52db39](https://github.com/Financial-Times/dotcom-tool-kit/commit/a52db39253108cd53494a3cffea043e8e89bdbf7)) - - -### Performance Improvements - -* improve lodash tree shaking ([454f9cd](https://github.com/Financial-Times/dotcom-tool-kit/commit/454f9cd9984162141c7318165d723593295db678)) - -### [2.6.2](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.6.1...types-v2.6.2) (2022-11-09) - - -### Bug Fixes - -* add tslib to individual plugins ([142363e](https://github.com/Financial-Times/dotcom-tool-kit/commit/142363edb2a82ebf4dc3c8e1b392888ebfd7dc89)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/error bumped from ^2.0.0 to ^2.0.1 - * @dotcom-tool-kit/logger bumped from ^2.1.1 to ^2.1.2 - -### [2.6.1](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.6.0...types-v2.6.1) (2022-09-21) - - -### Bug Fixes - -* prettier plugin respects .prettierignore ([2a15eab](https://github.com/Financial-Times/dotcom-tool-kit/commit/2a15eab2432cf9b0464bc3c4023f59f136350059)) - -## [2.6.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.5.1...types-v2.6.0) (2022-09-14) - - -### Features - -* deprecate config in favour for options in eslint ([831324a](https://github.com/Financial-Times/dotcom-tool-kit/commit/831324a40df17ca947fc000f51e011a2e79a4f91)) -* **node:** allow specifying ports ([20f797a](https://github.com/Financial-Times/dotcom-tool-kit/commit/20f797a9d547863c2e5fd3a40948ec62e575cbf8)) -* **node:** make vault optional ([cd12619](https://github.com/Financial-Times/dotcom-tool-kit/commit/cd12619346cfc92d67325c7ec4065a228e414f8c)) -* **nodemon:** allow specifying preferred ports ([0aab812](https://github.com/Financial-Times/dotcom-tool-kit/commit/0aab812dfab4eb778c5007eb6ddb2db99a9cc3b2)) -* **nodemon:** make vault optional ([9d28d95](https://github.com/Financial-Times/dotcom-tool-kit/commit/9d28d95b7b76fea14741f484d08abc19dc522911)) - -## [2.5.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.4.0...types-v2.5.0) (2022-07-27) - - -### Features - -* **types:** update Pa11y schema type ([8feb5fb](https://github.com/Financial-Times/dotcom-tool-kit/commit/8feb5fb685536805ae188e44c8905c5fe498ba4c)) - -## [2.4.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.3.0...types-v2.4.0) (2022-07-21) - - -### Features - -* add validation errors to compatibility test in types package ([ac118b3](https://github.com/Financial-Times/dotcom-tool-kit/commit/ac118b37bdbb30e062a2d559cc37dc36af4bcb73)) -* add validation errors to compatibility test in types package ([5228fab](https://github.com/Financial-Times/dotcom-tool-kit/commit/5228fab26ccee26bd786480bf280f6b91965679f)) -* loosen task and hook instance checks ([ac118b3](https://github.com/Financial-Times/dotcom-tool-kit/commit/ac118b37bdbb30e062a2d559cc37dc36af4bcb73)) -* loosen task and hook instance checks ([d79b7cf](https://github.com/Financial-Times/dotcom-tool-kit/commit/d79b7cfb5aed68be8b451dd2961f1abe3624c7b9)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/logger bumped from ^2.0.0 to ^2.1.0 - -## [2.3.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.2.0...types-v2.3.0) (2022-06-20) - - -### Features - -* **mocha:** allow plugin to pick up .mocharc files ([1ef9fd5](https://github.com/Financial-Times/dotcom-tool-kit/commit/1ef9fd51a50c4a7b53a9655befcb5943838bae97)) -* **node:** allow arbitrary arguments to be set for node process ([32cfe94](https://github.com/Financial-Times/dotcom-tool-kit/commit/32cfe946c49236e2170b625f49152f8f30ab1a15)) - -## [2.2.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.1.0...types-v2.2.0) (2022-06-07) - - -### Features - -* add options to pa11y plugin ([7670db7](https://github.com/Financial-Times/dotcom-tool-kit/commit/7670db7f59e9a798b5fc256182534c5c696f700a)) - -## [2.1.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v2.0.0...types-v2.1.0) (2022-05-06) - - -### Features - -* **webpack:** add watch mode command for run:local by default ([001a881](https://github.com/Financial-Times/dotcom-tool-kit/commit/001a881c85e5e123cc43075e367c3825c0538d4f)) - -## [2.0.0](https://github.com/Financial-Times/dotcom-tool-kit/compare/types-v1.9.0...types-v2.0.0) (2022-04-19) - - -### Miscellaneous Chores - -* release 2.0 version for all packages ([42dc5d3](https://github.com/Financial-Times/dotcom-tool-kit/commit/42dc5d39bf330b9bca4121d062470904f9c6918d)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @dotcom-tool-kit/error bumped from ^1.9.0 to ^2.0.0 diff --git a/lib/types/jest.config.js b/lib/types/jest.config.js deleted file mode 100644 index 24889bbe6..000000000 --- a/lib/types/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -const base = require('../../jest.config.base') - -module.exports = { - ...base -} diff --git a/lib/types/package.json b/lib/types/package.json deleted file mode 100644 index 558552759..000000000 --- a/lib/types/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "@dotcom-tool-kit/types", - "version": "3.6.0", - "description": "", - "main": "lib", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "FT.com Platforms Team ", - "license": "ISC", - "repository": { - "type": "git", - "url": "https://github.com/financial-times/dotcom-tool-kit.git", - "directory": "lib/types" - }, - "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", - "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/lib/types", - "files": [ - "/lib" - ], - "volta": { - "extends": "../../package.json" - }, - "dependencies": { - "@dotcom-tool-kit/conflict": "^1.0.0", - "@dotcom-tool-kit/error": "^3.2.0", - "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/validated": "^1.0.0", - "semver": "^7.3.7", - "tslib": "^2.3.1" - }, - "devDependencies": { - "@dotcom-tool-kit/schemas": "^1.0.0", - "@jest/globals": "^27.4.6", - "@types/prompts": "^2.0.14", - "@types/semver": "^7.3.9", - "winston": "^3.5.1", - "zod": "^3.22.4" - }, - "peerDependencies": { - "zod": "^3.22.4" - }, - "engines": { - "node": "16.x || 18.x || 20.x", - "npm": "7.x || 8.x || 9.x || 10.x" - } -} diff --git a/lib/types/src/index.ts b/lib/types/src/index.ts deleted file mode 100644 index 4e030b2dd..000000000 --- a/lib/types/src/index.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { Conflict } from '@dotcom-tool-kit/conflict' -import type { Validated } from '@dotcom-tool-kit/validated' -import type { SchemaOptions } from '@dotcom-tool-kit/schemas' - -export * from '@dotcom-tool-kit/validated' - -export type RCFile = { - plugins: string[] - installs: { [id: string]: string } - tasks: { [id: string]: string } - commands: { [id: string]: string | string[] } - options: { [id: string]: Record } - hooks: { [id: string]: Record }[] - init: string[] -} - -export interface Plugin { - id: string - root: string - rcFile?: RCFile - parent?: Plugin - children?: Plugin[] -} - -export interface CommandTask { - id: string - plugin: Plugin - tasks: string[] -} - -export interface PluginOptions { - options: Record - plugin: Plugin - forPlugin: Plugin -} - -export interface EntryPoint { - plugin: Plugin - modulePath: string -} - -export interface RawConfig { - root: string - plugins: { [id: string]: Validated } - resolvedPlugins: Set - tasks: { [id: string]: EntryPoint | Conflict } - commandTasks: { [id: string]: CommandTask | Conflict } - options: { [id: string]: PluginOptions | Conflict | undefined } - hooks: { [id: string]: EntryPoint | Conflict } - inits: EntryPoint[] -} - -export type ValidPluginsConfig = Omit & { - plugins: { [id: string]: Plugin } -} - -export type ValidPluginOptions = Omit & { - options: SchemaOptions[Id] -} - -export type ValidOptions = { - [Id in keyof SchemaOptions]: ValidPluginOptions -} - -export type ValidConfig = Omit & { - tasks: { [id: string]: EntryPoint } - commandTasks: { [id: string]: CommandTask } - options: ValidOptions - hooks: { [id: string]: EntryPoint } -} diff --git a/lib/types/tsconfig.json b/lib/types/tsconfig.json deleted file mode 100644 index 041f6efbe..000000000 --- a/lib/types/tsconfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": "../../tsconfig.settings.json", - "references": [ - { - "path": "../error" - }, - { - "path": "../logger" - }, - { - "path": "../validated" - }, - { - "path": "../schemas" - }, - { - "path": "../conflict" - } - ], - "compilerOptions": { - "outDir": "lib", - "rootDir": "src" - } -} diff --git a/lib/vault/package.json b/lib/vault/package.json index afaff234f..04009e9c2 100644 --- a/lib/vault/package.json +++ b/lib/vault/package.json @@ -9,7 +9,6 @@ "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/options": "^3.2.0", - "@dotcom-tool-kit/types": "^3.6.0", "@financial-times/n-fetch": "^1.0.0", "fs": "0.0.1-security", "os": "^0.1.2", diff --git a/package-lock.json b/package-lock.json index 47f66be87..920ac0dd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,11 +51,12 @@ "license": "MIT", "dependencies": { "@dotcom-tool-kit/base": "^3.4.1", + "@dotcom-tool-kit/config": "^1.0.0", "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/options": "^3.2.0", - "@dotcom-tool-kit/types": "^3.6.0", + "@dotcom-tool-kit/plugin": "^1.0.0", "@dotcom-tool-kit/validated": "^1.0.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "cosmiconfig": "^7.0.0", @@ -153,8 +154,8 @@ "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/plugin": "^1.0.0", "@dotcom-tool-kit/schemas": "^1.0.0", - "@dotcom-tool-kit/types": "^3.6.0", "@octokit/rest": "^19.0.5", "@quarterto/parse-makefile-rules": "^1.1.0", "cli-highlight": "^2.1.11", @@ -1133,12 +1134,23 @@ } }, "lib/base": { + "name": "@dotcom-tool-kit/base", "version": "3.4.1", "license": "ISC", "dependencies": { "@dotcom-tool-kit/conflict": "^1.0.0" } }, + "lib/config": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", + "@dotcom-tool-kit/plugin": "^1.0.0", + "@dotcom-tool-kit/schemas": "^1.0.0", + "@dotcom-tool-kit/validated": "^1.0.0" + } + }, "lib/conflict": { "name": "@dotcom-tool-kit/conflict", "version": "1.0.0", @@ -1153,7 +1165,6 @@ "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", "@dotcom-tool-kit/options": "^3.2.0", - "@dotcom-tool-kit/types": "^3.6.0", "@dotcom-tool-kit/vault": "^3.2.0", "tslib": "^2.3.1" }, @@ -1253,6 +1264,11 @@ "npm": "7.x || 8.x || 9.x || 10.x" } }, + "lib/plugin": { + "version": "1.0.0", + "license": "ISC", + "devDependencies": {} + }, "lib/schemas": { "name": "@dotcom-tool-kit/schemas", "version": "1.0.0", @@ -1340,6 +1356,7 @@ "lib/types": { "name": "@dotcom-tool-kit/types", "version": "3.6.0", + "extraneous": true, "license": "ISC", "dependencies": { "@dotcom-tool-kit/conflict": "^1.0.0", @@ -1365,20 +1382,6 @@ "zod": "^3.22.4" } }, - "lib/types/node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, - "lib/types/node_modules/zod": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "lib/validated": { "name": "@dotcom-tool-kit/validated", "version": "1.0.0", @@ -1394,7 +1397,6 @@ "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/options": "^3.2.0", - "@dotcom-tool-kit/types": "^3.6.0", "@financial-times/n-fetch": "^1.0.0", "fs": "0.0.1-security", "os": "^0.1.2", @@ -6350,6 +6352,10 @@ "resolved": "plugins/component", "link": true }, + "node_modules/@dotcom-tool-kit/config": { + "resolved": "lib/config", + "link": true + }, "node_modules/@dotcom-tool-kit/conflict": { "resolved": "lib/conflict", "link": true @@ -6438,6 +6444,10 @@ "resolved": "plugins/package-json-hook", "link": true }, + "node_modules/@dotcom-tool-kit/plugin": { + "resolved": "lib/plugin", + "link": true + }, "node_modules/@dotcom-tool-kit/prettier": { "resolved": "plugins/prettier", "link": true @@ -6454,10 +6464,6 @@ "resolved": "lib/state", "link": true }, - "node_modules/@dotcom-tool-kit/types": { - "resolved": "lib/types", - "link": true - }, "node_modules/@dotcom-tool-kit/typescript": { "resolved": "plugins/typescript", "link": true @@ -29106,7 +29112,6 @@ "dependencies": { "@dotcom-tool-kit/circleci": "^6.0.1", "@dotcom-tool-kit/npm": "^3.3.1", - "@dotcom-tool-kit/types": "^3.6.0", "tslib": "^2.3.1" }, "engines": { diff --git a/plugins/circleci-npm/package.json b/plugins/circleci-npm/package.json index 05943cc65..c7de0940c 100644 --- a/plugins/circleci-npm/package.json +++ b/plugins/circleci-npm/package.json @@ -10,7 +10,6 @@ "author": "FT.com Platforms Team ", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/types": "^3.6.0", "@dotcom-tool-kit/circleci": "^6.0.1", "@dotcom-tool-kit/npm": "^3.3.1", "tslib": "^2.3.1" From b127bc6b11b5b879ca96389e891e1c50f8aea391 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 5 Jan 2024 15:19:24 +0000 Subject: [PATCH 095/321] build: get all the package config and imports sorted out so it builds --- core/cli/src/config/validate-plugins.ts | 2 +- core/cli/src/init.ts | 5 +- core/cli/src/install.ts | 3 +- core/cli/src/messages.ts | 3 +- core/cli/src/plugin.ts | 3 +- core/cli/src/plugin/merge-commands.ts | 4 +- core/cli/src/plugin/merge-options.ts | 4 +- core/cli/src/plugin/reduce-installations.ts | 8 +- core/cli/src/tasks.ts | 3 +- core/cli/test/index.test.ts | 2 +- core/cli/tsconfig.json | 9 +- core/create/tsconfig.json | 5 +- lib/base/package.json | 16 +- lib/base/src/hook.ts | 4 +- lib/base/src/task.ts | 2 +- lib/base/tsconfig.json | 9 ++ lib/config/package.json | 2 +- lib/config/src/index.ts | 60 +++---- lib/config/tsconfig.json | 15 ++ lib/conflict/package.json | 6 +- lib/conflict/src/index.ts | 2 +- lib/conflict/tsconfig.json | 6 +- lib/doppler/tsconfig.json | 3 - lib/plugin/package.json | 2 +- lib/plugin/tsconfig.json | 7 + package-lock.json | 147 ++++++++++++------ plugins/nodemon/tsconfig.json | 7 +- plugins/package-json-hook/package.json | 1 + .../src/package-json-helper.ts | 3 +- plugins/package-json-hook/tsconfig.json | 7 +- release-please-config.json | 8 +- tsconfig.json | 14 +- 32 files changed, 252 insertions(+), 120 deletions(-) create mode 100644 lib/config/tsconfig.json create mode 100644 lib/plugin/tsconfig.json diff --git a/core/cli/src/config/validate-plugins.ts b/core/cli/src/config/validate-plugins.ts index 7b3661627..89e91b536 100644 --- a/core/cli/src/config/validate-plugins.ts +++ b/core/cli/src/config/validate-plugins.ts @@ -1,5 +1,5 @@ import type { RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' -import { type Validated, reduceValidated } from '@dotcom-tool-kit/validated' +import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' export function validatePlugins(config: RawConfig): Validated { const validatedPlugins = reduceValidated( diff --git a/core/cli/src/init.ts b/core/cli/src/init.ts index db80f8195..26b116da0 100644 --- a/core/cli/src/init.ts +++ b/core/cli/src/init.ts @@ -1,6 +1,7 @@ -import { Init, InitClass, ValidConfig } from '@dotcom-tool-kit/base' +import type { ValidConfig } from '@dotcom-tool-kit/config' +import { Init, InitClass } from '@dotcom-tool-kit/base' import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' -import { Logger } from 'winston' +import type { Logger } from 'winston' import { importEntryPoint } from './plugin/entry-point' const loadInitEntrypoints = async (logger: Logger, config: ValidConfig): Promise> => { diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 0ff4ddbe9..fb16cb2f5 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -5,7 +5,8 @@ import groupBy from 'lodash/groupBy' import type { Logger } from 'winston' import { loadConfig } from './config' import { hasConfigChanged, updateHashes } from './config/hash' -import { Hook, HookClass, ValidConfig } from '@dotcom-tool-kit/base' +import type { ValidConfig } from '@dotcom-tool-kit/config' +import { Hook, HookClass } from '@dotcom-tool-kit/base' import { Validated, invalid, reduceValidated, valid } from '@dotcom-tool-kit/validated' import { reducePluginHookInstallations } from './plugin/reduce-installations' import { findConflicts, withoutConflicts } from '@dotcom-tool-kit/conflict' diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index e5aa91bd5..4018b9177 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -1,5 +1,6 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' -import type { CommandTask, EntryPoint, Hook, Plugin, PluginOptions } from '@dotcom-tool-kit/base' +import type { Hook } from '@dotcom-tool-kit/base' +import type { CommandTask, EntryPoint, Plugin, PluginOptions } from '@dotcom-tool-kit/plugin' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' import type { Conflict } from '@dotcom-tool-kit/conflict' diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index f54bb2539..8f5f5d8e7 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,5 +1,6 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import { Plugin, RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' +import type { Plugin } from '@dotcom-tool-kit/plugin' +import type { RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' import { invalid, reduceValidated, valid, Validated } from '@dotcom-tool-kit/validated' import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts index bb7eb7727..429b5bc74 100644 --- a/core/cli/src/plugin/merge-commands.ts +++ b/core/cli/src/plugin/merge-commands.ts @@ -1,6 +1,6 @@ import type { CommandTask, Plugin } from '@dotcom-tool-kit/plugin' -import type {ValidPluginsConfig} from '@dotcom-tool-kit/config' -import { type Conflict, isConflict } from '@dotcom-tool-kit/conflict' +import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' +import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { isDescendent } from './is-descendent' export const mergePluginCommands = (config: ValidPluginsConfig, plugin: Plugin) => { diff --git a/core/cli/src/plugin/merge-options.ts b/core/cli/src/plugin/merge-options.ts index 6c1becbbd..605c4c268 100644 --- a/core/cli/src/plugin/merge-options.ts +++ b/core/cli/src/plugin/merge-options.ts @@ -1,7 +1,7 @@ -import type { Plugin, PluginOptions} from '@dotcom-tool-kit/plugin' +import type { Plugin, PluginOptions } from '@dotcom-tool-kit/plugin' import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isDescendent } from './is-descendent' -import { type Conflict, isConflict } from '@dotcom-tool-kit/conflict' +import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' // merge options from this plugin's config with any options we've collected already // TODO this is almost the exact same code as for command tasks, refactor diff --git a/core/cli/src/plugin/reduce-installations.ts b/core/cli/src/plugin/reduce-installations.ts index 75d74bc02..614994417 100644 --- a/core/cli/src/plugin/reduce-installations.ts +++ b/core/cli/src/plugin/reduce-installations.ts @@ -1,9 +1,9 @@ import type { Logger } from 'winston' import type { HookClass, HookInstallation } from '@dotcom-tool-kit/base' -import type { Plugin} from '@dotcom-tool-kit/plugin' -import type { ValidConfig} from '@dotcom-tool-kit/config' -import type { HookSchemas, HookOptions } from '@dotcom-tool-kit/schemas' -import { type Conflict, isConflict } from '@dotcom-tool-kit/conflict' +import type { Plugin } from '@dotcom-tool-kit/plugin' +import type { ValidConfig } from '@dotcom-tool-kit/config' +import { HookSchemas, HookOptions } from '@dotcom-tool-kit/schemas' +import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { groupBy } from 'lodash' // this function recursively collects all the hook installation requests from all plugins, diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index e9c010dab..128f9c7e3 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -1,4 +1,5 @@ -import { Task, TaskConstructor, ValidConfig } from '@dotcom-tool-kit/base' +import type { ValidConfig } from '@dotcom-tool-kit/config' +import { Task, TaskConstructor } from '@dotcom-tool-kit/base' import { Validated, reduceValidated } from '@dotcom-tool-kit/validated' import type { Logger } from 'winston' import { importEntryPoint } from './plugin/entry-point' diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index 9929791e1..5918de65d 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -4,7 +4,7 @@ import type { Plugin } from '@dotcom-tool-kit/plugin' import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { describe, expect, it, jest } from '@jest/globals' import * as path from 'path' -import winston, { type Logger } from 'winston' +import winston, { Logger } from 'winston' import { createConfig, validateConfig } from '../src/config' import { loadPlugin, resolvePlugin } from '../src/plugin' import { validatePlugins } from '../src/config/validate-plugins' diff --git a/core/cli/tsconfig.json b/core/cli/tsconfig.json index 5f51fbfe2..38a5a8ede 100644 --- a/core/cli/tsconfig.json +++ b/core/cli/tsconfig.json @@ -11,7 +11,10 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/plugin" + }, + { + "path": "../../lib/config" }, { "path": "../../lib/validated" @@ -24,7 +27,5 @@ "outDir": "lib", "rootDir": "src" }, - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/core/create/tsconfig.json b/core/create/tsconfig.json index 695961edc..55e3f7106 100644 --- a/core/create/tsconfig.json +++ b/core/create/tsconfig.json @@ -12,7 +12,10 @@ "path": "../../lib/logger" }, { - "path": "../../lib/types" + "path": "../../lib/config" + }, + { + "path": "../../lib/plugin" }, { "path": "../../lib/schemas" diff --git a/lib/base/package.json b/lib/base/package.json index 30346310a..ec210ad01 100644 --- a/lib/base/package.json +++ b/lib/base/package.json @@ -2,7 +2,7 @@ "name": "@dotcom-tool-kit/base", "version": "3.4.1", "description": "", - "main": "index.js", + "main": "lib", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, @@ -10,6 +10,18 @@ "author": "", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/conflict": "^1.0.0" + "@dotcom-tool-kit/conflict": "^1.0.0", + "@dotcom-tool-kit/validated": "^1.0.0", + "semver": "^7.5.4", + "winston": "^3.11.0" + }, + "devDependencies": { + "@dotcom-tool-kit/logger": "^3.3.0", + "@dotcom-tool-kit/plugin": "^1.0.0", + "winston": "^3.11.0", + "zod": "^3.22.4" + }, + "peerDependencies": { + "zod": "^3.22.4" } } diff --git a/lib/base/src/hook.ts b/lib/base/src/hook.ts index 01ae0900f..e862493a2 100644 --- a/lib/base/src/hook.ts +++ b/lib/base/src/hook.ts @@ -1,8 +1,8 @@ import type { Logger } from 'winston' import { Base } from './base' import { hookSymbol, typeSymbol } from './symbols' -import { z } from 'zod' -import { Plugin } from '../../types/src/index' +import type { z } from 'zod' +import type { Plugin } from '@dotcom-tool-kit/plugin' import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' export interface HookInstallation> { diff --git a/lib/base/src/task.ts b/lib/base/src/task.ts index f08fb3b43..59efe6df9 100644 --- a/lib/base/src/task.ts +++ b/lib/base/src/task.ts @@ -1,4 +1,4 @@ -import { z } from 'zod' +import type { z } from 'zod' import { Base } from './base' import { taskSymbol, typeSymbol } from './symbols' import type { Logger } from 'winston' diff --git a/lib/base/tsconfig.json b/lib/base/tsconfig.json index aa314f95c..04cf5f89a 100644 --- a/lib/base/tsconfig.json +++ b/lib/base/tsconfig.json @@ -3,6 +3,15 @@ "references": [ { "path": "../conflict" + }, + { + "path": "../logger" + }, + { + "path": "../plugin" + }, + { + "path": "../validated" } ], "compilerOptions": { diff --git a/lib/config/package.json b/lib/config/package.json index 1cbb5aaff..768f98d31 100644 --- a/lib/config/package.json +++ b/lib/config/package.json @@ -2,7 +2,7 @@ "name": "@dotcom-tool-kit/config", "version": "1.0.0", "description": "", - "main": "index.js", + "main": "lib", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts index 6cc39dc14..f5d1ffa59 100644 --- a/lib/config/src/index.ts +++ b/lib/config/src/index.ts @@ -1,34 +1,34 @@ -export type RCFile = { - plugins: string[] - installs: { [id: string]: string } - tasks: { [id: string]: string } - commands: { [id: string]: string | string[] } - options: { [id: string]: Record } - hooks: { [id: string]: Record }[] - init: string[] - } +import type { Validated } from '@dotcom-tool-kit/validated' +import type { EntryPoint, CommandTask, PluginOptions, Plugin } from '@dotcom-tool-kit/plugin' +import type { SchemaOptions } from '@dotcom-tool-kit/schemas' +import type { Conflict } from '@dotcom-tool-kit/conflict' - export interface Plugin { - id: string - root: string - rcFile?: RCFile - parent?: Plugin - children?: Plugin[] - } +export interface RawConfig { + root: string + plugins: { [id: string]: Validated } + resolvedPlugins: Set + tasks: { [id: string]: EntryPoint | Conflict } + commandTasks: { [id: string]: CommandTask | Conflict } + options: { [id: string]: PluginOptions | Conflict | undefined } + hooks: { [id: string]: EntryPoint | Conflict } + inits: EntryPoint[] +} - export interface CommandTask { - id: string - plugin: Plugin - tasks: string[] - } +export type ValidPluginsConfig = Omit & { + plugins: { [id: string]: Plugin } +} - export interface PluginOptions { - options: Record - plugin: Plugin - forPlugin: Plugin - } +export type ValidPluginOptions = Omit & { + options: SchemaOptions[Id] +} - export interface EntryPoint { - plugin: Plugin - modulePath: string - } +export type ValidOptions = { + [Id in keyof SchemaOptions]: ValidPluginOptions +} + +export type ValidConfig = Omit & { + tasks: { [id: string]: EntryPoint } + commandTasks: { [id: string]: CommandTask } + options: ValidOptions + hooks: { [id: string]: EntryPoint } +} diff --git a/lib/config/tsconfig.json b/lib/config/tsconfig.json new file mode 100644 index 000000000..4be408154 --- /dev/null +++ b/lib/config/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.settings.json", + "references": [ + { + "path": "../plugin" + }, + { + "path": "../schemas" + } + ], + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + } +} diff --git a/lib/conflict/package.json b/lib/conflict/package.json index ce8695fe4..72c13a87a 100644 --- a/lib/conflict/package.json +++ b/lib/conflict/package.json @@ -3,11 +3,13 @@ "version": "1.0.0", "description": "", "main": "lib", - "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", - "license": "ISC" + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/plugin": "^1.0.0" + } } diff --git a/lib/conflict/src/index.ts b/lib/conflict/src/index.ts index 2000faf98..c32d7f489 100644 --- a/lib/conflict/src/index.ts +++ b/lib/conflict/src/index.ts @@ -1,4 +1,4 @@ -import type { Plugin } from '../../types/src/index' +import type { Plugin } from '@dotcom-tool-kit/plugin' export interface Conflict { plugin: Plugin diff --git a/lib/conflict/tsconfig.json b/lib/conflict/tsconfig.json index c998ec643..ddc6f4964 100644 --- a/lib/conflict/tsconfig.json +++ b/lib/conflict/tsconfig.json @@ -1,6 +1,10 @@ { "extends": "../../tsconfig.settings.json", - "references": [], + "references": [ + { + "path": "../plugin" + } + ], "compilerOptions": { "outDir": "lib", "rootDir": "src" diff --git a/lib/doppler/tsconfig.json b/lib/doppler/tsconfig.json index aaa177477..b90c2969e 100644 --- a/lib/doppler/tsconfig.json +++ b/lib/doppler/tsconfig.json @@ -10,9 +10,6 @@ { "path": "../options" }, - { - "path": "../types" - }, { "path": "../vault" }, diff --git a/lib/plugin/package.json b/lib/plugin/package.json index be96e14a6..2e0d20364 100644 --- a/lib/plugin/package.json +++ b/lib/plugin/package.json @@ -2,7 +2,7 @@ "name": "@dotcom-tool-kit/plugin", "version": "1.0.0", "description": "", - "main": "index.js", + "main": "lib", "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" diff --git a/lib/plugin/tsconfig.json b/lib/plugin/tsconfig.json new file mode 100644 index 000000000..72bbe0165 --- /dev/null +++ b/lib/plugin/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.settings.json", + "compilerOptions": { + "outDir": "lib", + "rootDir": "src" + } +} diff --git a/package-lock.json b/package-lock.json index 920ac0dd4..1846da9fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -125,14 +125,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, - "core/cli/node_modules/zod": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "core/cli/node_modules/zod-validation-error": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-2.1.0.tgz", @@ -1096,14 +1088,6 @@ "node": ">=10" } }, - "core/create/node_modules/zod": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "core/sandbox": { "name": "@dotcom-tool-kit/sandbox", "version": "2.0.0", @@ -1138,10 +1122,98 @@ "version": "3.4.1", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/conflict": "^1.0.0" + "@dotcom-tool-kit/conflict": "^1.0.0", + "@dotcom-tool-kit/validated": "^1.0.0", + "semver": "^7.5.4", + "winston": "^3.11.0" + }, + "devDependencies": { + "@dotcom-tool-kit/logger": "^3.3.0", + "@dotcom-tool-kit/plugin": "^1.0.0", + "winston": "^3.11.0", + "zod": "^3.22.4" + }, + "peerDependencies": { + "zod": "^3.22.4" + } + }, + "lib/base/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "dev": true, + "engines": { + "node": ">=0.1.90" } }, + "lib/base/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "lib/base/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "lib/base/node_modules/winston": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz", + "integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==", + "dev": true, + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.7.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "lib/base/node_modules/winston-transport": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "dev": true, + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "lib/base/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "lib/config": { + "name": "@dotcom-tool-kit/config", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -1155,7 +1227,9 @@ "name": "@dotcom-tool-kit/conflict", "version": "1.0.0", "license": "ISC", - "devDependencies": {} + "dependencies": { + "@dotcom-tool-kit/plugin": "^1.0.0" + } }, "lib/doppler": { "name": "@dotcom-tool-kit/doppler", @@ -1265,6 +1339,7 @@ } }, "lib/plugin": { + "name": "@dotcom-tool-kit/plugin", "version": "1.0.0", "license": "ISC", "devDependencies": {} @@ -1327,15 +1402,6 @@ "node": ">= 12.0.0" } }, - "lib/schemas/node_modules/zod": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "lib/state": { "name": "@dotcom-tool-kit/state", "version": "3.3.0", @@ -28945,6 +29011,14 @@ "node": ">= 6" } }, + "node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "plugins/babel": { "name": "@dotcom-tool-kit/babel", "version": "3.2.0", @@ -29226,15 +29300,6 @@ "node": ">= 14" } }, - "plugins/circleci/node_modules/zod": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "plugins/component": { "name": "@dotcom-tool-kit/component", "version": "4.1.3", @@ -30295,6 +30360,7 @@ "dependencies": { "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/conflict": "^1.0.0", + "@dotcom-tool-kit/plugin": "^1.0.0", "@financial-times/package-json": "^3.0.0", "lodash": "^4.17.21", "tslib": "^2.3.1" @@ -30319,15 +30385,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "plugins/package-json-hook/node_modules/zod": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "plugins/prettier": { "name": "@dotcom-tool-kit/prettier", "version": "3.2.0", diff --git a/plugins/nodemon/tsconfig.json b/plugins/nodemon/tsconfig.json index 03b725021..86abc26c2 100644 --- a/plugins/nodemon/tsconfig.json +++ b/plugins/nodemon/tsconfig.json @@ -5,6 +5,9 @@ "rootDir": "src" }, "references": [ + { + "path": "../../core/cli" + }, { "path": "../../lib/base" }, @@ -24,7 +27,5 @@ "path": "../../lib/schemas" } ], - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/plugins/package-json-hook/package.json b/plugins/package-json-hook/package.json index 3dbc8a490..35b110e9d 100644 --- a/plugins/package-json-hook/package.json +++ b/plugins/package-json-hook/package.json @@ -12,6 +12,7 @@ "dependencies": { "@dotcom-tool-kit/base": "^3.4.1", "@dotcom-tool-kit/conflict": "^1.0.0", + "@dotcom-tool-kit/plugin": "^1.0.0", "@financial-times/package-json": "^3.0.0", "lodash": "^4.17.21", "tslib": "^2.3.1" diff --git a/plugins/package-json-hook/src/package-json-helper.ts b/plugins/package-json-hook/src/package-json-helper.ts index b6c9686e6..461178300 100644 --- a/plugins/package-json-hook/src/package-json-helper.ts +++ b/plugins/package-json-hook/src/package-json-helper.ts @@ -1,5 +1,6 @@ import type { z } from 'zod' -import { Hook, HookInstallation, Plugin } from '@dotcom-tool-kit/base' +import { Hook, HookInstallation } from '@dotcom-tool-kit/base' +import type { Plugin } from '@dotcom-tool-kit/plugin' import fs from 'fs' import get from 'lodash/get' import set from 'lodash/set' diff --git a/plugins/package-json-hook/tsconfig.json b/plugins/package-json-hook/tsconfig.json index 093ffa39a..b3b24cebb 100644 --- a/plugins/package-json-hook/tsconfig.json +++ b/plugins/package-json-hook/tsconfig.json @@ -13,9 +13,10 @@ }, { "path": "../../lib/conflict" + }, + { + "path": "../../lib/plugin" } ], - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } diff --git a/release-please-config.json b/release-please-config.json index 66a24b65d..b444ce935 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -7,13 +7,16 @@ "packages": { "core/cli": {}, "core/create": {}, + "lib/base": {}, + "lib/config": {}, + "lib/conflict": {}, "lib/doppler": {}, "lib/error": {}, "lib/logger": {}, "lib/options": {}, - "plugins/package-json-hook": {}, + "lib/plugin": {}, + "lib/schemas": {}, "lib/state": {}, - "lib/types": {}, "lib/validated": {}, "lib/vault": {}, "lib/wait-for-ok": {}, @@ -44,6 +47,7 @@ "plugins/node": {}, "plugins/nodemon": {}, "plugins/npm": {}, + "plugins/package-json-hook": {}, "plugins/pa11y": {}, "plugins/prettier": {}, "plugins/serverless": {}, diff --git a/tsconfig.json b/tsconfig.json index d7262bdac..44b614346 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -62,7 +62,19 @@ "path": "core/create" }, { - "path": "lib/types" + "path": "lib/config" + }, + { + "path": "lib/plugin" + }, + { + "path": "lib/validated" + }, + { + "path": "lib/conflict" + }, + { + "path": "lib/base" }, { "path": "plugins/prettier" From 06c078536112271ccfffa049f23ffbe0c2fc0eb5 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Jan 2024 15:43:18 +0000 Subject: [PATCH 096/321] style: consistent import spacing Co-authored-by: Alex Cerda --- core/cli/src/plugin/entry-point.ts | 2 +- core/cli/src/plugin/merge-hooks.ts | 2 +- core/cli/src/plugin/merge-tasks.ts | 2 +- core/create/src/prompts/conflicts.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/cli/src/plugin/entry-point.ts b/core/cli/src/plugin/entry-point.ts index 13a3f05ca..c33d5ee03 100644 --- a/core/cli/src/plugin/entry-point.ts +++ b/core/cli/src/plugin/entry-point.ts @@ -1,7 +1,7 @@ import { styles as s } from '@dotcom-tool-kit/logger' import type { Base } from '@dotcom-tool-kit/base' -import type {EntryPoint} from '@dotcom-tool-kit/plugin' +import type { EntryPoint } from '@dotcom-tool-kit/plugin' import { Validated, invalid } from '@dotcom-tool-kit/validated' import resolvePkg from 'resolve-pkg' import { isPlainObject } from 'lodash' diff --git a/core/cli/src/plugin/merge-hooks.ts b/core/cli/src/plugin/merge-hooks.ts index 2cfb5e774..6b1d33424 100644 --- a/core/cli/src/plugin/merge-hooks.ts +++ b/core/cli/src/plugin/merge-hooks.ts @@ -1,5 +1,5 @@ import type { EntryPoint, Plugin } from '@dotcom-tool-kit/plugin' -import type {ValidPluginsConfig} from '@dotcom-tool-kit/config' +import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isConflict } from '@dotcom-tool-kit/conflict' export const mergePluginHooks = (config: ValidPluginsConfig, plugin: Plugin) => { diff --git a/core/cli/src/plugin/merge-tasks.ts b/core/cli/src/plugin/merge-tasks.ts index 013a21a10..78e81c4ff 100644 --- a/core/cli/src/plugin/merge-tasks.ts +++ b/core/cli/src/plugin/merge-tasks.ts @@ -1,5 +1,5 @@ import type{ EntryPoint, Plugin } from '@dotcom-tool-kit/plugin' -import type {ValidPluginsConfig } from '@dotcom-tool-kit/config' +import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isConflict } from '@dotcom-tool-kit/conflict' // add plugin tasks to our task registry, handling any conflicts diff --git a/core/create/src/prompts/conflicts.ts b/core/create/src/prompts/conflicts.ts index cc254593b..e21086b32 100644 --- a/core/create/src/prompts/conflicts.ts +++ b/core/create/src/prompts/conflicts.ts @@ -1,6 +1,6 @@ import * as ToolkitErrorModule from '@dotcom-tool-kit/error' import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' -import type { RCFile} from '@dotcom-tool-kit/plugin' +import type { RCFile } from '@dotcom-tool-kit/plugin' import type { ValidConfig } from '@dotcom-tool-kit/config' import type installHooksType from 'dotcom-tool-kit/lib/install' import { promises as fs } from 'fs' From 79adabd7f6f02885bc3ad83d4fab910a479d8c6e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 5 Jan 2024 16:47:07 +0000 Subject: [PATCH 097/321] build: explicitly add @types/prettier to prettier plugin --- package-lock.json | 7 +++++++ plugins/prettier/package.json | 1 + 2 files changed, 8 insertions(+) diff --git a/package-lock.json b/package-lock.json index 1846da9fb..a707ab21b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30401,6 +30401,7 @@ }, "devDependencies": { "@jest/globals": "^27.4.6", + "@types/prettier": "^2.7.3", "jest": "^27.4.7", "ts-jest": "^27.1.3", "winston": "^3.5.1" @@ -30413,6 +30414,12 @@ "dotcom-tool-kit": "3.x" } }, + "plugins/prettier/node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true + }, "plugins/prettier/node_modules/tslib": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", diff --git a/plugins/prettier/package.json b/plugins/prettier/package.json index e151fa631..dd50b3df1 100644 --- a/plugins/prettier/package.json +++ b/plugins/prettier/package.json @@ -32,6 +32,7 @@ ], "devDependencies": { "@jest/globals": "^27.4.6", + "@types/prettier": "^2.7.3", "jest": "^27.4.7", "ts-jest": "^27.1.3", "winston": "^3.5.1" From 92a4c0081f50df5472096ca401665431ed3b4995 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Jan 2024 15:58:00 +0000 Subject: [PATCH 098/321] fix: use resolve-from for entrypoints as resolve-pkg expects a package.json --- core/cli/package.json | 1 + core/cli/src/plugin/entry-point.ts | 3 ++- package-lock.json | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/cli/package.json b/core/cli/package.json index 5dfebffdb..a1404c3cb 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -53,6 +53,7 @@ "cosmiconfig": "^7.0.0", "lodash": "^4.17.21", "minimist": "^1.2.5", + "resolve-from": "^5.0.0", "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", "yaml": "^1.10.2", diff --git a/core/cli/src/plugin/entry-point.ts b/core/cli/src/plugin/entry-point.ts index c33d5ee03..2fdf64171 100644 --- a/core/cli/src/plugin/entry-point.ts +++ b/core/cli/src/plugin/entry-point.ts @@ -3,6 +3,7 @@ import { styles as s } from '@dotcom-tool-kit/logger' import type { Base } from '@dotcom-tool-kit/base' import type { EntryPoint } from '@dotcom-tool-kit/plugin' import { Validated, invalid } from '@dotcom-tool-kit/validated' +import resolveFrom from 'resolve-from' import resolvePkg from 'resolve-pkg' import { isPlainObject } from 'lodash' import { indentReasons } from '../messages' @@ -15,7 +16,7 @@ export async function importEntryPoint> { - const resolvedPath = resolvePkg(entryPoint.modulePath, { cwd: entryPoint.plugin.root }) + const resolvedPath = resolveFrom.silent(entryPoint.plugin.root, entryPoint.modulePath) if (!resolvedPath) { return invalid([ diff --git a/package-lock.json b/package-lock.json index a707ab21b..fb21c4f51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,6 +62,7 @@ "cosmiconfig": "^7.0.0", "lodash": "^4.17.21", "minimist": "^1.2.5", + "resolve-from": "^5.0.0", "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", "yaml": "^1.10.2", From 83c4594932c9ed9ad798613c79842e3856c57baa Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Jan 2024 16:06:43 +0000 Subject: [PATCH 099/321] =?UTF-8?q?fix:=20look=20in=20config.commandTasks?= =?UTF-8?q?=20for=20defined=20commands,=20not=20config.hooks=20?= =?UTF-8?q?=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/cli/src/tasks.ts | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 128f9c7e3..252b013c1 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -12,7 +12,6 @@ import { shouldDisableNativeFetch } from './fetch' import { runInit } from './init' type ErrorSummary = { - hook: string task: string error: Error } @@ -41,22 +40,22 @@ const loadTasks = async ( return reduceValidated(taskResults).map(Object.fromEntries) } -export async function runTasks(logger: Logger, hooks: string[], files?: string[]): Promise { +export async function runTasks(logger: Logger, commands: string[], files?: string[]): Promise { const config = await loadConfig(logger) - const availableHooks = Object.keys(config.hooks) + const availableCommands = Object.keys(config.commandTasks) .sort() .map((id) => `- ${id}`) .join('\n') - const missingHooks = hooks.filter((id) => !config.hooks[id]) + const missingCommands = commands.filter((id) => !config.commandTasks[id]) - if (missingHooks.length > 0) { - const error = new ToolKitError(`hooks ${missingHooks} do not exist`) - error.details = `maybe you need to install a plugin to handle these hooks, or configure them in your Tool Kit configuration. + if (missingCommands.length > 0) { + const error = new ToolKitError(`commands ${missingCommands} do not exist`) + error.details = `maybe you need to install a plugin to define these commands, or configure them in your Tool Kit configuration. -hooks that are available are: -${availableHooks}` +commands that are available are: +${availableCommands}` throw error } @@ -74,25 +73,25 @@ ${availableHooks}` process.execArgv.push('--no-experimental-fetch') } - const taskNames = hooks.flatMap((hook) => config.commandTasks[hook]?.tasks ?? []) + const taskNames = commands.flatMap((command) => config.commandTasks[command]?.tasks ?? []) const tasks = (await loadTasks(logger, taskNames, config)).unwrap('tasks are invalid') - for (const hook of hooks) { + for (const command of commands) { const errors: ErrorSummary[] = [] - if (!config.commandTasks[hook]) { - logger.warn(`no task configured for ${hook}: skipping assignment...`) + if (!config.commandTasks[command]) { + logger.warn(`no task configured for ${command}: skipping assignment...`) continue } - for (const id of config.commandTasks[hook].tasks) { + for (const id of config.commandTasks[command].tasks) { try { logger.info(styles.taskHeader(`running ${styles.task(id)} task`)) await tasks[id].run(files) } catch (error) { - // allow subsequent hook tasks to run on error + // TODO use validated for this + // allow subsequent command tasks to run on error errors.push({ - hook, task: id, error: error as Error }) @@ -100,7 +99,7 @@ ${availableHooks}` } if (errors.length > 0) { - const error = new ToolKitError(`error running tasks for ${styles.hook(hook)}`) + const error = new ToolKitError(`error running tasks for ${styles.hook(command)}`) error.details = errors .map( ({ task, error }) => From 5f20426c49e293931bba92eacfd624354d5cc7b5 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 11:28:13 +0100 Subject: [PATCH 100/321] build: update prettier --- package-lock.json | 568 +++++++++++++++++++++++++++++----------------- package.json | 2 +- 2 files changed, 358 insertions(+), 212 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb21c4f51..d39d3c312 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,7 @@ "husky": "^4.3.8", "jest": "^27.4.7", "lint-staged": "^10.5.4", - "prettier": "2.2.1", + "prettier": "^2.8.8", "release-please": "^15.0.0", "ts-jest": "^27.1.3", "typescript": "~4.9.5" @@ -1090,32 +1090,13 @@ } }, "core/sandbox": { - "name": "@dotcom-tool-kit/sandbox", - "version": "2.0.0", - "extraneous": true, + "name": "@financial-times/sandbox", + "version": "1.0.0", "license": "ISC", - "devDependencies": { - "@dotcom-tool-kit/circleci-heroku": "^2.0.0", - "@dotcom-tool-kit/circleci-npm": "^4.0.0", - "@dotcom-tool-kit/eslint": "^2.0.0", - "@dotcom-tool-kit/frontend-app": "^2.0.0", - "@dotcom-tool-kit/jest": "^2.0.0", - "@dotcom-tool-kit/lint-staged": "^3.0.0", - "@dotcom-tool-kit/lint-staged-npm": "^2.0.0", - "@dotcom-tool-kit/mocha": "^2.0.0", - "@dotcom-tool-kit/n-test": "^2.0.0", - "@dotcom-tool-kit/next-router": "^2.0.0", - "@dotcom-tool-kit/nodemon": "^2.0.0", - "@dotcom-tool-kit/npm": "^2.0.0", - "@dotcom-tool-kit/pa11y": "^0.3.0", - "@dotcom-tool-kit/prettier": "^2.0.0", - "@dotcom-tool-kit/upload-assets-to-s3": "^2.0.0", - "dotcom-tool-kit": "^2.0.0", - "nodemon": "^2.0.15" - }, - "engines": { - "node": "16.x || 18.x", - "npm": "7.x || 8.x || 9.x" + "dependencies": { + "@dotcom-tool-kit/base": "file:../../lib/base", + "@dotcom-tool-kit/package-json-hook": "file:../../plugins/package-json-hook", + "dotcom-tool-kit": "file:../cli" } }, "lib/base": { @@ -6656,6 +6637,10 @@ "version": "3.0.0", "license": "MIT" }, + "node_modules/@financial-times/sandbox": { + "resolved": "core/sandbox", + "link": true + }, "node_modules/@gar/promisify": { "version": "1.1.3", "license": "MIT" @@ -10741,12 +10726,15 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10844,16 +10832,17 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -11003,9 +10992,12 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -11822,13 +11814,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13239,6 +13236,54 @@ "node": ">=10" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/dateformat": { "version": "3.0.3", "dev": true, @@ -13629,16 +13674,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-lazy-prop": { @@ -14142,49 +14190,56 @@ } }, "node_modules/es-abstract": { - "version": "1.22.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", - "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.5", - "es-set-tostringtag": "^2.0.1", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.2", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "hasown": "^2.0.0", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.13" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -14193,14 +14248,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -15871,15 +15956,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -15945,11 +16034,13 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "license": "MIT", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -16215,19 +16306,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "license": "MIT", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -16246,10 +16338,11 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "license": "MIT", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -16362,9 +16455,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -16990,11 +17083,11 @@ } }, "node_modules/internal-slot": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", - "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dependencies": { - "get-intrinsic": "^1.2.2", + "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" }, @@ -17068,13 +17161,15 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -17175,6 +17270,20 @@ "node": ">=0.10.0" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "license": "MIT", @@ -17332,8 +17441,9 @@ "peer": true }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "license": "MIT", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "engines": { "node": ">= 0.4" }, @@ -17412,7 +17522,8 @@ }, "node_modules/is-regex": { "version": "1.1.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -17439,10 +17550,14 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "license": "MIT", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -17496,11 +17611,11 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -21393,12 +21508,12 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -22925,6 +23040,14 @@ "node": ">=0.10.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "dev": true, @@ -22942,13 +23065,17 @@ } }, "node_modules/prettier": { - "version": "2.2.1", - "license": "MIT", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/pretty-format": { @@ -23663,13 +23790,14 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -24212,12 +24340,12 @@ "license": "0BSD" }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -24245,14 +24373,17 @@ } }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -25339,27 +25470,30 @@ "license": "ISC" }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -26125,13 +26259,14 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -26141,26 +26276,29 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -27200,27 +27338,28 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -27230,15 +27369,16 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -27248,13 +27388,19 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -28590,15 +28736,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index daa70c68c..e0c7938a8 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "husky": "^4.3.8", "jest": "^27.4.7", "lint-staged": "^10.5.4", - "prettier": "2.2.1", + "prettier": "^2.8.8", "release-please": "^15.0.0", "ts-jest": "^27.1.3", "typescript": "~4.9.5" From 9eaa9b0475a471769d5b86fe103139aadfd6e8a6 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 14:19:17 +0000 Subject: [PATCH 101/321] feat!: move plugin options to a sub key of toolkitrc options entries --- core/cli/src/plugin/merge-options.ts | 2 +- core/cli/src/rc-file.ts | 18 +++++- .../files/conflict-resolution/.toolkitrc.yml | 23 ++++---- core/cli/test/files/duplicate/.toolkitrc.yml | 23 ++++---- core/cli/test/files/successful/.toolkitrc.yml | 15 ++--- core/create/src/index.ts | 2 +- core/create/src/prompts/oidc.ts | 4 +- core/create/src/prompts/options.ts | 27 +++++---- lib/plugin/src/index.ts | 58 +++++++++---------- 9 files changed, 95 insertions(+), 77 deletions(-) diff --git a/core/cli/src/plugin/merge-options.ts b/core/cli/src/plugin/merge-options.ts index 605c4c268..f65ab7b12 100644 --- a/core/cli/src/plugin/merge-options.ts +++ b/core/cli/src/plugin/merge-options.ts @@ -7,7 +7,7 @@ import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' // TODO this is almost the exact same code as for command tasks, refactor export const mergePluginOptions = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { - for (const [id, configOptions] of Object.entries(plugin.rcFile.options)) { + for (const [id, configOptions] of Object.entries(plugin.rcFile.options.plugins ?? {})) { // users can specify root options with the dotcom-tool-kit key to mirror // the name of the root npm package const pluginId = id === 'dotcom-tool-kit' ? 'app root' : id diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index de5319a46..5a702f5f6 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -5,11 +5,23 @@ import * as path from 'path' import type { Logger } from 'winston' export const explorer = cosmiconfig('toolkit', { ignoreEmptySearchPlaces: false }) -const emptyConfig = { plugins: [], installs: {}, tasks: {}, commands: {}, options: {}, hooks: [], init: [] } +const emptyConfig = { + plugins: [], + installs: {}, + tasks: {}, + commands: {}, + options: { plugins: {} }, + hooks: [], + init: [] +} satisfies RCFile let rootConfig: string | undefined type RawRCFile = { - [key in keyof RCFile]?: RCFile[key] | null + [key in Exclude]?: RCFile[key] | null +} & { + options: { + [key in keyof RCFile['options']]?: RCFile['options'][key] | null + } } export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boolean): Promise { @@ -38,7 +50,7 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo installs: config.installs ?? {}, tasks: config.tasks ?? {}, commands: config.commands ?? {}, - options: config.options ?? {}, + options: config.options ? { plugins: config.options.plugins ?? {} } : { plugins: {} }, hooks: config.hooks ?? [], init: config.init ?? [] } diff --git a/core/cli/test/files/conflict-resolution/.toolkitrc.yml b/core/cli/test/files/conflict-resolution/.toolkitrc.yml index 537d7d76d..4bf53682e 100644 --- a/core/cli/test/files/conflict-resolution/.toolkitrc.yml +++ b/core/cli/test/files/conflict-resolution/.toolkitrc.yml @@ -5,17 +5,18 @@ plugins: - '@dotcom-tool-kit/heroku' # for build:remote hook and build:local via npm plugin options: - '@dotcom-tool-kit/heroku': - pipeline: tool-kit-test - systemCode: tool-kit-test - scaling: - tool-kit-test: - web: - size: standard-1x - quantity: 1 - '@dotcom-tool-kit/vault': - team: platforms - app: tool-kit-test + plugins: + '@dotcom-tool-kit/heroku': + pipeline: tool-kit-test + systemCode: tool-kit-test + scaling: + tool-kit-test: + web: + size: standard-1x + quantity: 1 + '@dotcom-tool-kit/vault': + team: platforms + app: tool-kit-test commands: build:local: diff --git a/core/cli/test/files/duplicate/.toolkitrc.yml b/core/cli/test/files/duplicate/.toolkitrc.yml index b0f181d5c..3b29e8687 100644 --- a/core/cli/test/files/duplicate/.toolkitrc.yml +++ b/core/cli/test/files/duplicate/.toolkitrc.yml @@ -3,16 +3,17 @@ plugins: - '@dotcom-tool-kit/heroku' options: - '@dotcom-tool-kit/heroku': - pipeline: tool-kit-test - systemCode: tool-kit-test - scaling: - tool-kit-test: - web: - size: standard-1x - quantity: 1 - '@dotcom-tool-kit/vault': - team: platforms - app: tool-kit-test + plugins: + '@dotcom-tool-kit/heroku': + pipeline: tool-kit-test + systemCode: tool-kit-test + scaling: + tool-kit-test: + web: + size: standard-1x + quantity: 1 + '@dotcom-tool-kit/vault': + team: platforms + app: tool-kit-test commands: diff --git a/core/cli/test/files/successful/.toolkitrc.yml b/core/cli/test/files/successful/.toolkitrc.yml index 0fc808aee..abceebdcc 100644 --- a/core/cli/test/files/successful/.toolkitrc.yml +++ b/core/cli/test/files/successful/.toolkitrc.yml @@ -5,13 +5,14 @@ plugins: - '@dotcom-tool-kit/circleci-deploy' # test:local hook via npm plugin and test:ci hook options: - '@dotcom-tool-kit/eslint': - files: - - webpack.config.js - '@dotcom-tool-kit/mocha': - testDir: './mocha_tests' - '@dotcom-tool-kit/n-test': - host: 'https://example.com' + plugins: + '@dotcom-tool-kit/eslint': + files: + - webpack.config.js + '@dotcom-tool-kit/mocha': + testDir: './mocha_tests' + '@dotcom-tool-kit/n-test': + host: 'https://example.com' commands: 'test:local': diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 2802960d2..023bb586c 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -116,7 +116,7 @@ async function main() { installs: {}, tasks: {}, commands: {}, - options: {}, + options: { plugins: {} }, hooks: [], init: [] } diff --git a/core/create/src/prompts/oidc.ts b/core/create/src/prompts/oidc.ts index 30423c343..aa72e9c3f 100644 --- a/core/create/src/prompts/oidc.ts +++ b/core/create/src/prompts/oidc.ts @@ -256,8 +256,8 @@ export default async function oidcPrompt({ toolKitConfig }: OidcParams): Promise // Kit vault plugin options. The class tries to read the options from // the global options object so let's set these options based on what's // been selected during the options prompt. - setOptions('@dotcom-tool-kit/vault', toolKitConfig.options['@dotcom-tool-kit/vault']) - setOptions('@dotcom-tool-kit/doppler', toolKitConfig.options['@dotcom-tool-kit/doppler']) + setOptions('@dotcom-tool-kit/vault', toolKitConfig.options.plugins['@dotcom-tool-kit/vault']) + setOptions('@dotcom-tool-kit/doppler', toolKitConfig.options.plugins['@dotcom-tool-kit/doppler']) const dopplerProjectName = new DopplerEnvVars(winstonLogger, 'prod').options.project const ssmAction = 'ssm:GetParameter' const ssmResource = `arn:aws:ssm:eu-west-1:\${AWS::AccountId}:parameter/${dopplerProjectName}/*` diff --git a/core/create/src/prompts/options.ts b/core/create/src/prompts/options.ts index 4dd054840..8b2e46864 100644 --- a/core/create/src/prompts/options.ts +++ b/core/create/src/prompts/options.ts @@ -51,7 +51,7 @@ async function optionsPromptForPlugin( { onCancel } ) if (stringOption !== '') { - toolKitConfig.options[plugin][optionName] = stringOption + toolKitConfig.options.plugins[plugin][optionName] = stringOption } break case 'ZodBoolean': @@ -67,7 +67,7 @@ async function optionsPromptForPlugin( }, { onCancel } ) - toolKitConfig.options[plugin][optionName] = boolOption + toolKitConfig.options.plugins[plugin][optionName] = boolOption break case 'ZodNumber': const { numberOption } = await prompt( @@ -80,7 +80,7 @@ async function optionsPromptForPlugin( { onCancel } ) if (numberOption !== '') { - toolKitConfig.options[plugin][optionName] = Number.parseFloat(numberOption) + toolKitConfig.options.plugins[plugin][optionName] = Number.parseFloat(numberOption) } break case 'ZodArray': @@ -98,7 +98,9 @@ async function optionsPromptForPlugin( { onCancel } ) if (stringArrayOption !== '' && stringArrayOption !== undefined) { - toolKitConfig.options[plugin][optionName] = stringArrayOption.split(',').map((s) => s.trim()) + toolKitConfig.options.plugins[plugin][optionName] = stringArrayOption + .split(',') + .map((s) => s.trim()) } break case 'ZodNumber': @@ -113,7 +115,7 @@ async function optionsPromptForPlugin( { onCancel } ) if (numberArrayOption !== '' && numberArrayOption !== undefined) { - toolKitConfig.options[plugin][optionName] = numberArrayOption + toolKitConfig.options.plugins[plugin][optionName] = numberArrayOption .split(',') .map((s) => Number.parseFloat(s.trim())) } @@ -135,7 +137,7 @@ async function optionsPromptForPlugin( { onCancel } ) if (option !== '') { - toolKitConfig.options[plugin][optionName] = option + toolKitConfig.options.plugins[plugin][optionName] = option } break } @@ -154,7 +156,7 @@ async function optionsPromptForPlugin( { onCancel } ) if (option !== '') { - toolKitConfig.options[plugin][optionName] = option + toolKitConfig.options.plugins[plugin][optionName] = option } break case 'ZodUnion': @@ -199,6 +201,8 @@ export default async ({ configPath, bizOpsSystem }: OptionsParams): Promise => { + toolKitConfig.options.plugins = {} + for (const plugin of Object.keys(config.plugins)) { let options: z.AnyZodObject let generators: PromptGenerators | undefined @@ -224,7 +228,6 @@ export default async ({ const anyRequired = required.length > 0 const styledPlugin = styles.plugin(pluginName) - toolKitConfig.options[plugin] = {} if (anyRequired) { winstonLogger.info(`Please now configure the options for the ${styledPlugin} plugin.`) @@ -238,7 +241,7 @@ export default async ({ * the object is partial because not all options for a plugin will * have generators, but all values in the record will be defined **/ - toolKitConfig.options[plugin][optionName] = await generator!( + toolKitConfig.options.plugins![plugin][optionName] = await generator!( winstonLogger.child({ plugin }), prompt, onCancel, @@ -256,12 +259,12 @@ export default async ({ plugin, required .map(([name, type]) => ({ name, type })) - .filter(({ name }) => !toolKitConfig.options[plugin][name]) + .filter(({ name }) => !toolKitConfig.options.plugins[plugin][name]) ) } if (cancelled) { - delete toolKitConfig.options[plugin] + delete toolKitConfig.options.plugins[plugin] return true } } @@ -286,7 +289,7 @@ export default async ({ }) ) } else if (!anyRequired) { - delete toolKitConfig.options[plugin] + delete toolKitConfig.options.plugins[plugin] } } } diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts index 6cc39dc14..cd5dffa9c 100644 --- a/lib/plugin/src/index.ts +++ b/lib/plugin/src/index.ts @@ -1,34 +1,34 @@ export type RCFile = { - plugins: string[] - installs: { [id: string]: string } - tasks: { [id: string]: string } - commands: { [id: string]: string | string[] } - options: { [id: string]: Record } - hooks: { [id: string]: Record }[] - init: string[] - } + plugins: string[] + installs: { [id: string]: string } + tasks: { [id: string]: string } + commands: { [id: string]: string | string[] } + options: { plugins: { [id: string]: Record } } + hooks: { [id: string]: Record }[] + init: string[] +} - export interface Plugin { - id: string - root: string - rcFile?: RCFile - parent?: Plugin - children?: Plugin[] - } +export interface Plugin { + id: string + root: string + rcFile?: RCFile + parent?: Plugin + children?: Plugin[] +} - export interface CommandTask { - id: string - plugin: Plugin - tasks: string[] - } +export interface CommandTask { + id: string + plugin: Plugin + tasks: string[] +} - export interface PluginOptions { - options: Record - plugin: Plugin - forPlugin: Plugin - } +export interface PluginOptions { + options: Record + plugin: Plugin + forPlugin: Plugin +} - export interface EntryPoint { - plugin: Plugin - modulePath: string - } +export interface EntryPoint { + plugin: Plugin + modulePath: string +} From 78672ea0e14d8706774b3eb537d25bee0295cff7 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 14:25:52 +0000 Subject: [PATCH 102/321] refactor: rename options in config to pluginOptions --- core/cli/src/config.ts | 6 +++--- core/cli/src/help.ts | 2 +- core/cli/src/install.ts | 2 +- core/cli/src/plugin/merge-options.ts | 8 ++++---- core/cli/src/plugin/options.ts | 4 ++-- core/cli/src/tasks.ts | 2 +- lib/config/src/index.ts | 6 +++--- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index d4883282c..9c37ca7af 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -31,7 +31,7 @@ export const createConfig = (): RawConfig => ({ resolvedPlugins: new Set(), tasks: {}, commandTasks: {}, - options: {}, + pluginOptions: {}, hooks: {}, inits: [] }) @@ -42,7 +42,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali const commandTaskConflicts = findConflicts(Object.values(config.commandTasks)) const hookConflicts = findConflictingEntries(config.hooks) const taskConflicts = findConflictingEntries(config.tasks) - const optionConflicts = findConflicts(Object.values(config.options)) + const optionConflicts = findConflicts(Object.values(config.pluginOptions)) const definedCommandTaskConflicts = commandTaskConflicts.filter((conflict) => { return conflict.conflicting[0].id in config.hooks @@ -107,7 +107,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali error.details += formatInvalidOptions(invalidOptions) } - const unusedOptions = Object.entries(config.options) + const unusedOptions = Object.entries(config.pluginOptions) .filter( ([, option]) => option && !isConflict(option) && !option.forPlugin && option.plugin.root === process.cwd() diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index fb2b8981e..0a7c23860 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -10,7 +10,7 @@ export default async function showHelp(logger: Logger, hooks: string[]): Promise hooks = Object.keys(config.hooks).sort() } - for (const pluginOptions of Object.values(config.options)) { + for (const pluginOptions of Object.values(config.pluginOptions)) { if (pluginOptions.forPlugin) { setOptions(pluginOptions.forPlugin.id as OptionKey, pluginOptions.options) } diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index fb16cb2f5..9ea0be94c 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -101,7 +101,7 @@ export async function checkInstall(logger: Logger, config: ValidConfig): Promise export default async function installHooks(logger: Logger): Promise { const config = await loadConfig(logger) - for (const pluginOptions of Object.values(config.options)) { + for (const pluginOptions of Object.values(config.pluginOptions)) { if (pluginOptions.forPlugin) { setOptions(pluginOptions.forPlugin.id as OptionKey, pluginOptions.options) } diff --git a/core/cli/src/plugin/merge-options.ts b/core/cli/src/plugin/merge-options.ts index f65ab7b12..b9dd76f72 100644 --- a/core/cli/src/plugin/merge-options.ts +++ b/core/cli/src/plugin/merge-options.ts @@ -11,7 +11,7 @@ export const mergePluginOptions = (config: ValidPluginsConfig, plugin: Plugin) = // users can specify root options with the dotcom-tool-kit key to mirror // the name of the root npm package const pluginId = id === 'dotcom-tool-kit' ? 'app root' : id - const existingOptions = config.options[pluginId] + const existingOptions = config.pluginOptions[pluginId] const pluginOptions: PluginOptions = { options: configOptions, @@ -33,15 +33,15 @@ export const mergePluginOptions = (config: ValidPluginsConfig, plugin: Plugin) = conflicting: conflicting.concat(pluginOptions) } - config.options[pluginId] = conflict + config.pluginOptions[pluginId] = conflict } else { // if we're here, any existing options are from a child plugin, // so merge in overrides from the parent - config.options[pluginId] = { ...existingOptions, ...pluginOptions } + config.pluginOptions[pluginId] = { ...existingOptions, ...pluginOptions } } } else { // this options key might not have been set yet, in which case use the new one - config.options[pluginId] = pluginOptions + config.pluginOptions[pluginId] = pluginOptions } } } diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index 77f44fe52..5d34adaa3 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -9,7 +9,7 @@ export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig for (const [id, plugin] of Object.entries(config.plugins)) { const pluginId = id as keyof SchemaOptions - const pluginOptions = config.options[pluginId] + const pluginOptions = config.pluginOptions[pluginId] if (pluginOptions && isConflict(pluginOptions)) { continue } @@ -28,7 +28,7 @@ export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig // `Foo` and the other as `Foo | Foo | Foo` for // some reason (something to do with the record indexing) and it can't // unify them. But they are equivalent so let's force it with a cast. - config.options[pluginId] = { + config.pluginOptions[pluginId] = { options: result.data, plugin: config.plugins['app root'], forPlugin: plugin diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 252b013c1..a3c5f0c73 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -59,7 +59,7 @@ ${availableCommands}` throw error } - for (const pluginOptions of Object.values(config.options)) { + for (const pluginOptions of Object.values(config.pluginOptions)) { if (pluginOptions.forPlugin) { setOptions(pluginOptions.forPlugin.id as OptionKey, pluginOptions.options) } diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts index f5d1ffa59..42bc8961b 100644 --- a/lib/config/src/index.ts +++ b/lib/config/src/index.ts @@ -9,7 +9,7 @@ export interface RawConfig { resolvedPlugins: Set tasks: { [id: string]: EntryPoint | Conflict } commandTasks: { [id: string]: CommandTask | Conflict } - options: { [id: string]: PluginOptions | Conflict | undefined } + pluginOptions: { [id: string]: PluginOptions | Conflict | undefined } hooks: { [id: string]: EntryPoint | Conflict } inits: EntryPoint[] } @@ -26,9 +26,9 @@ export type ValidOptions = { [Id in keyof SchemaOptions]: ValidPluginOptions } -export type ValidConfig = Omit & { +export type ValidConfig = Omit & { tasks: { [id: string]: EntryPoint } commandTasks: { [id: string]: CommandTask } - options: ValidOptions + pluginOptions: ValidOptions hooks: { [id: string]: EntryPoint } } From e725e3eb94d7f058a4da18427831d500471005b1 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 14:27:02 +0000 Subject: [PATCH 103/321] refactor: rename PluginOptions to OptionsForPlugin --- core/cli/src/messages.ts | 6 +++--- core/cli/src/plugin/merge-options.ts | 6 +++--- lib/config/src/index.ts | 6 +++--- lib/plugin/src/index.ts | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 4018b9177..4375bcc20 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -1,6 +1,6 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' import type { Hook } from '@dotcom-tool-kit/base' -import type { CommandTask, EntryPoint, Plugin, PluginOptions } from '@dotcom-tool-kit/plugin' +import type { CommandTask, EntryPoint, Plugin, OptionsForPlugin } from '@dotcom-tool-kit/plugin' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' import type { Conflict } from '@dotcom-tool-kit/conflict' @@ -50,12 +50,12 @@ You must resolve this conflict by explicitly configuring which task to run for t ` -const formatOptionConflict = (conflict: Conflict): string => `${s.plugin( +const formatOptionConflict = (conflict: Conflict): string => `${s.plugin( conflict.conflicting[0].forPlugin.id )}, configured by: ${conflict.conflicting.map((option) => `- ${s.plugin(option.plugin.id)}`)}` -export const formatOptionConflicts = (conflicts: Conflict[]): string => `${s.heading( +export const formatOptionConflicts = (conflicts: Conflict[]): string => `${s.heading( 'These plugins have conflicting options' )}: diff --git a/core/cli/src/plugin/merge-options.ts b/core/cli/src/plugin/merge-options.ts index b9dd76f72..d2e3ea509 100644 --- a/core/cli/src/plugin/merge-options.ts +++ b/core/cli/src/plugin/merge-options.ts @@ -1,4 +1,4 @@ -import type { Plugin, PluginOptions } from '@dotcom-tool-kit/plugin' +import type { Plugin, OptionsForPlugin } from '@dotcom-tool-kit/plugin' import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isDescendent } from './is-descendent' import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' @@ -13,7 +13,7 @@ export const mergePluginOptions = (config: ValidPluginsConfig, plugin: Plugin) = const pluginId = id === 'dotcom-tool-kit' ? 'app root' : id const existingOptions = config.pluginOptions[pluginId] - const pluginOptions: PluginOptions = { + const pluginOptions: OptionsForPlugin = { options: configOptions, plugin, forPlugin: config.plugins[pluginId] @@ -28,7 +28,7 @@ export const mergePluginOptions = (config: ValidPluginsConfig, plugin: Plugin) = if (!existingFromDescendent) { const conflicting = isConflict(existingOptions) ? existingOptions.conflicting : [existingOptions] - const conflict: Conflict = { + const conflict: Conflict = { plugin, conflicting: conflicting.concat(pluginOptions) } diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts index 42bc8961b..05ddd8703 100644 --- a/lib/config/src/index.ts +++ b/lib/config/src/index.ts @@ -1,5 +1,5 @@ import type { Validated } from '@dotcom-tool-kit/validated' -import type { EntryPoint, CommandTask, PluginOptions, Plugin } from '@dotcom-tool-kit/plugin' +import type { EntryPoint, CommandTask, OptionsForPlugin, Plugin } from '@dotcom-tool-kit/plugin' import type { SchemaOptions } from '@dotcom-tool-kit/schemas' import type { Conflict } from '@dotcom-tool-kit/conflict' @@ -9,7 +9,7 @@ export interface RawConfig { resolvedPlugins: Set tasks: { [id: string]: EntryPoint | Conflict } commandTasks: { [id: string]: CommandTask | Conflict } - pluginOptions: { [id: string]: PluginOptions | Conflict | undefined } + pluginOptions: { [id: string]: OptionsForPlugin | Conflict | undefined } hooks: { [id: string]: EntryPoint | Conflict } inits: EntryPoint[] } @@ -18,7 +18,7 @@ export type ValidPluginsConfig = Omit & { plugins: { [id: string]: Plugin } } -export type ValidPluginOptions = Omit & { +export type ValidPluginOptions = Omit & { options: SchemaOptions[Id] } diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts index cd5dffa9c..f47c9325a 100644 --- a/lib/plugin/src/index.ts +++ b/lib/plugin/src/index.ts @@ -22,7 +22,7 @@ export interface CommandTask { tasks: string[] } -export interface PluginOptions { +export interface OptionsForPlugin { options: Record plugin: Plugin forPlugin: Plugin From 7de862654fe2ca474ddfd6b28bc133a4de17c803 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 14:28:58 +0000 Subject: [PATCH 104/321] refactor!: rename SchemaOptions to PluginOptions and make schemas package exports more consistent --- core/cli/src/plugin/options.ts | 4 ++-- lib/config/src/index.ts | 8 ++++---- lib/options/src/index.ts | 10 +++++----- lib/schemas/src/hooks.ts | 2 +- lib/schemas/src/index.ts | 4 ++-- lib/schemas/src/plugins.ts | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index 5d34adaa3..01f3401c4 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -1,6 +1,6 @@ import { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { InvalidOption } from '../messages' -import { SchemaOptions, PluginSchemas } from '@dotcom-tool-kit/schemas' +import { type PluginOptions, PluginSchemas } from '@dotcom-tool-kit/schemas' import { isConflict } from '@dotcom-tool-kit/conflict' import type { Logger } from 'winston' @@ -8,7 +8,7 @@ export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig const invalidOptions: InvalidOption[] = [] for (const [id, plugin] of Object.entries(config.plugins)) { - const pluginId = id as keyof SchemaOptions + const pluginId = id as keyof PluginOptions const pluginOptions = config.pluginOptions[pluginId] if (pluginOptions && isConflict(pluginOptions)) { continue diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts index 05ddd8703..c7e79329e 100644 --- a/lib/config/src/index.ts +++ b/lib/config/src/index.ts @@ -1,6 +1,6 @@ import type { Validated } from '@dotcom-tool-kit/validated' import type { EntryPoint, CommandTask, OptionsForPlugin, Plugin } from '@dotcom-tool-kit/plugin' -import type { SchemaOptions } from '@dotcom-tool-kit/schemas' +import type { PluginOptions } from '@dotcom-tool-kit/schemas' import type { Conflict } from '@dotcom-tool-kit/conflict' export interface RawConfig { @@ -18,12 +18,12 @@ export type ValidPluginsConfig = Omit & { plugins: { [id: string]: Plugin } } -export type ValidPluginOptions = Omit & { - options: SchemaOptions[Id] +export type ValidPluginOptions = Omit & { + options: PluginOptions[Id] } export type ValidOptions = { - [Id in keyof SchemaOptions]: ValidPluginOptions + [Id in keyof PluginOptions]: ValidPluginOptions } export type ValidConfig = Omit & { diff --git a/lib/options/src/index.ts b/lib/options/src/index.ts index 5aa2f8f38..6ad4d64e1 100644 --- a/lib/options/src/index.ts +++ b/lib/options/src/index.ts @@ -1,11 +1,11 @@ -import type { SchemaOptions } from '@dotcom-tool-kit/schemas' +import type { PluginOptions } from '@dotcom-tool-kit/schemas' -const options: Partial = {} +const options: Partial = {} -export type OptionKey = keyof SchemaOptions +export type OptionKey = keyof PluginOptions -export const getOptions = (plugin: T): SchemaOptions[T] | undefined => options[plugin] +export const getOptions = (plugin: T): PluginOptions[T] | undefined => options[plugin] -export const setOptions = (plugin: T, opts: SchemaOptions[T]): void => { +export const setOptions = (plugin: T, opts: PluginOptions[T]): void => { options[plugin] = opts } diff --git a/lib/schemas/src/hooks.ts b/lib/schemas/src/hooks.ts index c6c8a4820..05911ee14 100644 --- a/lib/schemas/src/hooks.ts +++ b/lib/schemas/src/hooks.ts @@ -7,7 +7,7 @@ export const HookSchemas = { } // Gives the TypeScript type represented by each Schema -export type Options = { +export type HookOptions = { [plugin in keyof typeof HookSchemas]: typeof HookSchemas[plugin] extends z.ZodTypeAny ? z.infer : never diff --git a/lib/schemas/src/index.ts b/lib/schemas/src/index.ts index 2dbfa5317..dd997fe16 100644 --- a/lib/schemas/src/index.ts +++ b/lib/schemas/src/index.ts @@ -1,3 +1,3 @@ -export { Options as SchemaOptions, Schemas as PluginSchemas } from './plugins' -export { Options as HookOptions, HookSchemas } from './hooks' +export * from './plugins' +export * from './hooks' export * from './prompts' diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 4bc714ddd..2b6ea0512 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -22,7 +22,7 @@ import { UploadAssetsToS3Schema } from './plugins/upload-assets-to-s3' import { VaultSchema } from './plugins/vault' import { WebpackSchema } from './plugins/webpack' -export const Schemas = { +export const PluginSchemas = { 'app root': RootSchema, '@dotcom-tool-kit/babel': BabelSchema, '@dotcom-tool-kit/circleci': CircleCISchema, @@ -47,8 +47,8 @@ export const Schemas = { } // Gives the TypeScript type represented by each Schema -export type Options = { - [plugin in keyof typeof Schemas]: typeof Schemas[plugin] extends z.ZodTypeAny - ? z.infer +export type PluginOptions = { + [plugin in keyof typeof PluginSchemas]: (typeof PluginSchemas)[plugin] extends z.ZodTypeAny + ? z.infer<(typeof PluginSchemas)[plugin]> : never } From a7e68911148679be4138cb7ebf8ecc55b45a4e28 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 14:34:15 +0000 Subject: [PATCH 105/321] feat: add (empty) schema exports for task schemas (and make the zod inference helper type generic) --- lib/schemas/src/hooks.ts | 10 ++-------- lib/schemas/src/index.ts | 3 ++- lib/schemas/src/infer.ts | 6 ++++++ lib/schemas/src/plugins.ts | 10 ++-------- lib/schemas/src/tasks.ts | 5 +++++ 5 files changed, 17 insertions(+), 17 deletions(-) create mode 100644 lib/schemas/src/infer.ts create mode 100644 lib/schemas/src/tasks.ts diff --git a/lib/schemas/src/hooks.ts b/lib/schemas/src/hooks.ts index 05911ee14..f1241a131 100644 --- a/lib/schemas/src/hooks.ts +++ b/lib/schemas/src/hooks.ts @@ -1,14 +1,8 @@ -import { z } from 'zod' - import { PackageJsonSchema } from './hooks/package-json' +import { type InferSchemaOptions } from './infer' export const HookSchemas = { PackageJson: PackageJsonSchema } -// Gives the TypeScript type represented by each Schema -export type HookOptions = { - [plugin in keyof typeof HookSchemas]: typeof HookSchemas[plugin] extends z.ZodTypeAny - ? z.infer - : never -} +export type HookOptions = InferSchemaOptions diff --git a/lib/schemas/src/index.ts b/lib/schemas/src/index.ts index dd997fe16..360babd76 100644 --- a/lib/schemas/src/index.ts +++ b/lib/schemas/src/index.ts @@ -1,3 +1,4 @@ -export * from './plugins' export * from './hooks' +export * from './plugins' export * from './prompts' +export * from './tasks' diff --git a/lib/schemas/src/infer.ts b/lib/schemas/src/infer.ts new file mode 100644 index 000000000..dd88c3312 --- /dev/null +++ b/lib/schemas/src/infer.ts @@ -0,0 +1,6 @@ +import { type z } from 'zod' + +// Gives the TypeScript type represented by each Schema +export type InferSchemaOptions = { + [key in keyof Schemas]: Schemas[key] extends z.ZodTypeAny ? z.infer : never +} diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 2b6ea0512..7d1559cb5 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -1,5 +1,3 @@ -import type { z } from 'zod' - import { BabelSchema } from './plugins/babel' import { CircleCISchema } from './plugins/circleci' import { CypressSchema } from './plugins/cypress' @@ -21,6 +19,7 @@ import { TypeScriptSchema } from './plugins/typescript' import { UploadAssetsToS3Schema } from './plugins/upload-assets-to-s3' import { VaultSchema } from './plugins/vault' import { WebpackSchema } from './plugins/webpack' +import { type InferSchemaOptions } from './infer' export const PluginSchemas = { 'app root': RootSchema, @@ -46,9 +45,4 @@ export const PluginSchemas = { '@dotcom-tool-kit/webpack': WebpackSchema } -// Gives the TypeScript type represented by each Schema -export type PluginOptions = { - [plugin in keyof typeof PluginSchemas]: (typeof PluginSchemas)[plugin] extends z.ZodTypeAny - ? z.infer<(typeof PluginSchemas)[plugin]> - : never -} +export type PluginOptions = InferSchemaOptions diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts new file mode 100644 index 000000000..804afcd33 --- /dev/null +++ b/lib/schemas/src/tasks.ts @@ -0,0 +1,5 @@ +import { type InferSchemaOptions } from './infer' + +export const TaskSchemas = {} + +export type TaskOptions = InferSchemaOptions From e749170d67a82064d205b7304b536c6c06a633c5 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 14:56:37 +0000 Subject: [PATCH 106/321] feat: load plugin rcfile task options into config --- core/cli/src/config.ts | 1 + core/cli/src/plugin.ts | 4 +- ...rge-options.ts => merge-plugin-options.ts} | 2 +- core/cli/src/plugin/merge-task-options.ts | 46 +++++++++++++++++++ core/cli/src/rc-file.ts | 6 ++- core/create/src/index.ts | 2 +- lib/config/src/index.ts | 9 +++- lib/plugin/src/index.ts | 11 ++++- 8 files changed, 74 insertions(+), 7 deletions(-) rename core/cli/src/plugin/{merge-options.ts => merge-plugin-options.ts} (98%) create mode 100644 core/cli/src/plugin/merge-task-options.ts diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 9c37ca7af..c9ae5b10d 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -32,6 +32,7 @@ export const createConfig = (): RawConfig => ({ tasks: {}, commandTasks: {}, pluginOptions: {}, + taskOptions: {}, hooks: {}, inits: [] }) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 8f5f5d8e7..7cd7aa576 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -9,8 +9,9 @@ import { indentReasons } from './messages' import { mergePluginTasks } from './plugin/merge-tasks' import { mergePluginHooks } from './plugin/merge-hooks' import { mergePluginCommands } from './plugin/merge-commands' -import { mergePluginOptions } from './plugin/merge-options' +import { mergePluginOptions } from './plugin/merge-plugin-options' import { mergePluginInits } from './plugin/merge-inits' +import { mergeTaskOptions } from './plugin/merge-task-options' export async function loadPlugin( id: string, @@ -78,6 +79,7 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger mergePluginHooks(config, plugin) mergePluginCommands(config, plugin) mergePluginOptions(config, plugin) + mergeTaskOptions(config, plugin) mergePluginInits(config, plugin) config.resolvedPlugins.add(plugin.id) diff --git a/core/cli/src/plugin/merge-options.ts b/core/cli/src/plugin/merge-plugin-options.ts similarity index 98% rename from core/cli/src/plugin/merge-options.ts rename to core/cli/src/plugin/merge-plugin-options.ts index d2e3ea509..7dba580fe 100644 --- a/core/cli/src/plugin/merge-options.ts +++ b/core/cli/src/plugin/merge-plugin-options.ts @@ -7,7 +7,7 @@ import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' // TODO this is almost the exact same code as for command tasks, refactor export const mergePluginOptions = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { - for (const [id, configOptions] of Object.entries(plugin.rcFile.options.plugins ?? {})) { + for (const [id, configOptions] of Object.entries(plugin.rcFile.options.plugins)) { // users can specify root options with the dotcom-tool-kit key to mirror // the name of the root npm package const pluginId = id === 'dotcom-tool-kit' ? 'app root' : id diff --git a/core/cli/src/plugin/merge-task-options.ts b/core/cli/src/plugin/merge-task-options.ts new file mode 100644 index 000000000..d4ebd392f --- /dev/null +++ b/core/cli/src/plugin/merge-task-options.ts @@ -0,0 +1,46 @@ +import type { Plugin, OptionsForTask } from '@dotcom-tool-kit/plugin' +import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' +import { type Conflict, isConflict } from '@dotcom-tool-kit/conflict' + +import { isDescendent } from './is-descendent' + +// merge options from this plugin's config with any options we've collected already +// TODO this is almost the exact same code as for command tasks, refactor +export const mergeTaskOptions = (config: ValidPluginsConfig, plugin: Plugin) => { + if (plugin.rcFile) { + for (const [taskId, configOptions] of Object.entries(plugin.rcFile.options.tasks)) { + const existingOptions = config.taskOptions[taskId] + + const taskOptions: OptionsForTask = { + options: configOptions, + plugin, + task: taskId + } + + if (existingOptions) { + const existingFromDescendent = isDescendent(plugin, existingOptions.plugin) + + // plugins can only override options from their descendents, otherwise it's a conflict + // return a conflict either listing these options and the sibling's, + // or merging in previously-generated options + if (!existingFromDescendent) { + const conflicting = isConflict(existingOptions) ? existingOptions.conflicting : [existingOptions] + + const conflict: Conflict = { + plugin, + conflicting: conflicting.concat(taskOptions) + } + + config.taskOptions[taskId] = conflict + } else { + // if we're here, any existing options are from a child plugin, + // so merge in overrides from the parent + config.taskOptions[taskId] = { ...existingOptions, ...taskOptions } + } + } else { + // this options key might not have been set yet, in which case use the new one + config.taskOptions[taskId] = taskOptions + } + } + } +} diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 5a702f5f6..5e7d53c55 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -10,7 +10,7 @@ const emptyConfig = { installs: {}, tasks: {}, commands: {}, - options: { plugins: {} }, + options: { plugins: {}, tasks: {} }, hooks: [], init: [] } satisfies RCFile @@ -50,7 +50,9 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo installs: config.installs ?? {}, tasks: config.tasks ?? {}, commands: config.commands ?? {}, - options: config.options ? { plugins: config.options.plugins ?? {} } : { plugins: {} }, + options: config.options + ? { plugins: config.options.plugins ?? {}, tasks: config.options.tasks ?? {} } + : { plugins: {}, tasks: {} }, hooks: config.hooks ?? [], init: config.init ?? [] } diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 023bb586c..5c7442815 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -116,7 +116,7 @@ async function main() { installs: {}, tasks: {}, commands: {}, - options: { plugins: {} }, + options: { plugins: {}, tasks: {} }, hooks: [], init: [] } diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts index c7e79329e..91d99eb26 100644 --- a/lib/config/src/index.ts +++ b/lib/config/src/index.ts @@ -1,5 +1,11 @@ import type { Validated } from '@dotcom-tool-kit/validated' -import type { EntryPoint, CommandTask, OptionsForPlugin, Plugin } from '@dotcom-tool-kit/plugin' +import type { + CommandTask, + EntryPoint, + Plugin, + OptionsForPlugin, + OptionsForTask +} from '@dotcom-tool-kit/plugin' import type { PluginOptions } from '@dotcom-tool-kit/schemas' import type { Conflict } from '@dotcom-tool-kit/conflict' @@ -10,6 +16,7 @@ export interface RawConfig { tasks: { [id: string]: EntryPoint | Conflict } commandTasks: { [id: string]: CommandTask | Conflict } pluginOptions: { [id: string]: OptionsForPlugin | Conflict | undefined } + taskOptions: { [id: string]: OptionsForTask | Conflict | undefined } hooks: { [id: string]: EntryPoint | Conflict } inits: EntryPoint[] } diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts index f47c9325a..0cc0830ef 100644 --- a/lib/plugin/src/index.ts +++ b/lib/plugin/src/index.ts @@ -3,7 +3,10 @@ export type RCFile = { installs: { [id: string]: string } tasks: { [id: string]: string } commands: { [id: string]: string | string[] } - options: { plugins: { [id: string]: Record } } + options: { + plugins: { [id: string]: Record } + tasks: { [id: string]: Record } + } hooks: { [id: string]: Record }[] init: string[] } @@ -28,6 +31,12 @@ export interface OptionsForPlugin { forPlugin: Plugin } +export interface OptionsForTask { + options: Record + plugin: Plugin + task: string +} + export interface EntryPoint { plugin: Plugin modulePath: string From babc2a7e4815656c9b0b6a806dd8412ee07fab1a Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 15:35:54 +0000 Subject: [PATCH 107/321] refactor: rename some of the merge methods for clarity --- core/cli/src/plugin.ts | 16 ++++++++-------- core/cli/src/plugin/merge-commands.ts | 2 +- core/cli/src/plugin/merge-hooks.ts | 2 +- core/cli/src/plugin/merge-inits.ts | 2 +- core/cli/src/plugin/merge-tasks.ts | 4 ++-- core/cli/src/plugin/options.ts | 6 +----- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 7cd7aa576..3ad455bc9 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -6,11 +6,11 @@ import resolvePkg from 'resolve-pkg' import type { Logger } from 'winston' import { loadToolKitRC } from './rc-file' import { indentReasons } from './messages' -import { mergePluginTasks } from './plugin/merge-tasks' -import { mergePluginHooks } from './plugin/merge-hooks' -import { mergePluginCommands } from './plugin/merge-commands' +import { mergeTasks } from './plugin/merge-tasks' +import { mergeHooks } from './plugin/merge-hooks' +import { mergeCommands } from './plugin/merge-commands' import { mergePluginOptions } from './plugin/merge-plugin-options' -import { mergePluginInits } from './plugin/merge-inits' +import { mergeInits } from './plugin/merge-inits' import { mergeTaskOptions } from './plugin/merge-task-options' export async function loadPlugin( @@ -75,12 +75,12 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger } } - mergePluginTasks(config, plugin) - mergePluginHooks(config, plugin) - mergePluginCommands(config, plugin) + mergeTasks(config, plugin) + mergeHooks(config, plugin) + mergeCommands(config, plugin) mergePluginOptions(config, plugin) mergeTaskOptions(config, plugin) - mergePluginInits(config, plugin) + mergeInits(config, plugin) config.resolvedPlugins.add(plugin.id) } diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts index 429b5bc74..c63bd4f2c 100644 --- a/core/cli/src/plugin/merge-commands.ts +++ b/core/cli/src/plugin/merge-commands.ts @@ -3,7 +3,7 @@ import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { isDescendent } from './is-descendent' -export const mergePluginCommands = (config: ValidPluginsConfig, plugin: Plugin) => { +export const mergeCommands = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { for (const [id, configCommandTask] of Object.entries(plugin.rcFile.commands)) { // handle conflicts between commands from different plugins diff --git a/core/cli/src/plugin/merge-hooks.ts b/core/cli/src/plugin/merge-hooks.ts index 6b1d33424..eb1cd36db 100644 --- a/core/cli/src/plugin/merge-hooks.ts +++ b/core/cli/src/plugin/merge-hooks.ts @@ -2,7 +2,7 @@ import type { EntryPoint, Plugin } from '@dotcom-tool-kit/plugin' import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isConflict } from '@dotcom-tool-kit/conflict' -export const mergePluginHooks = (config: ValidPluginsConfig, plugin: Plugin) => { +export const mergeHooks = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { // add hooks to the registry, handling any conflicts // TODO refactor with command conflict handler diff --git a/core/cli/src/plugin/merge-inits.ts b/core/cli/src/plugin/merge-inits.ts index eeab89324..89a5c2372 100644 --- a/core/cli/src/plugin/merge-inits.ts +++ b/core/cli/src/plugin/merge-inits.ts @@ -1,7 +1,7 @@ import type { Plugin } from '@dotcom-tool-kit/plugin' import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' -export const mergePluginInits = (config: ValidPluginsConfig, plugin: Plugin) => { +export const mergeInits = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { // no conflict resolution needed; we'll just run them all ig config.inits.push( diff --git a/core/cli/src/plugin/merge-tasks.ts b/core/cli/src/plugin/merge-tasks.ts index 78e81c4ff..cfecacbea 100644 --- a/core/cli/src/plugin/merge-tasks.ts +++ b/core/cli/src/plugin/merge-tasks.ts @@ -1,9 +1,9 @@ -import type{ EntryPoint, Plugin } from '@dotcom-tool-kit/plugin' +import type { EntryPoint, Plugin } from '@dotcom-tool-kit/plugin' import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isConflict } from '@dotcom-tool-kit/conflict' // add plugin tasks to our task registry, handling any conflicts -export const mergePluginTasks = (config: ValidPluginsConfig, plugin: Plugin) => { +export const mergeTasks = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { for (const [taskName, modulePath] of Object.entries(plugin.rcFile.tasks || {})) { const existingTaskId = config.tasks[taskName] diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index 01f3401c4..80bd05346 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -24,15 +24,11 @@ export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig // Set up options entry for plugins that don't have options specified // explicitly. They could still have default options that are set by zod. if (!pluginOptions) { - // TypeScript struggles with this type as it sees one side as - // `Foo` and the other as `Foo | Foo | Foo` for - // some reason (something to do with the record indexing) and it can't - // unify them. But they are equivalent so let's force it with a cast. config.pluginOptions[pluginId] = { options: result.data, plugin: config.plugins['app root'], forPlugin: plugin - } as any // eslint-disable-line @typescript-eslint/no-explicit-any + } } else { pluginOptions.options = result.data } From 1eee8535c7984e07235f93e8a9b0a3081ad68b4e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 16:14:21 +0000 Subject: [PATCH 108/321] refactor!: rename Task#options to pluginOptions --- lib/base/src/task.ts | 13 ++++++------- plugins/babel/src/tasks/development.ts | 2 +- plugins/babel/src/tasks/production.ts | 2 +- plugins/cypress/src/tasks/local.ts | 4 ++-- plugins/eslint/src/tasks/eslint.ts | 4 ++-- plugins/heroku/src/tasks/production.ts | 4 ++-- plugins/heroku/src/tasks/review.ts | 4 ++-- plugins/heroku/src/tasks/staging.ts | 4 ++-- plugins/jest/src/tasks/ci.ts | 2 +- plugins/jest/src/tasks/local.ts | 2 +- plugins/mocha/src/tasks/mocha.ts | 6 +++--- plugins/n-test/src/tasks/n-test.ts | 10 +++++----- plugins/next-router/src/tasks/next-router.ts | 2 +- plugins/node/src/tasks/node.ts | 2 +- plugins/nodemon/src/tasks/nodemon.ts | 2 +- plugins/pa11y/src/tasks/pa11y.ts | 2 +- plugins/prettier/src/tasks/prettier.ts | 6 +++--- plugins/serverless/src/tasks/deploy.ts | 2 +- plugins/serverless/src/tasks/provision.ts | 2 +- plugins/serverless/src/tasks/run.ts | 2 +- plugins/typescript/src/tasks/typescript.ts | 8 ++++---- .../src/tasks/upload-assets-to-s3.ts | 2 +- plugins/webpack/src/tasks/development.ts | 2 +- plugins/webpack/src/tasks/production.ts | 2 +- plugins/webpack/src/tasks/watch.ts | 2 +- 25 files changed, 46 insertions(+), 47 deletions(-) diff --git a/lib/base/src/task.ts b/lib/base/src/task.ts index 59efe6df9..54e936ace 100644 --- a/lib/base/src/task.ts +++ b/lib/base/src/task.ts @@ -3,9 +3,8 @@ import { Base } from './base' import { taskSymbol, typeSymbol } from './symbols' import type { Logger } from 'winston' -export abstract class Task extends Base { +export abstract class Task extends Base { static description: string - id: string static get [typeSymbol](): symbol { return taskSymbol @@ -15,14 +14,14 @@ export abstract class Task extends Base { return taskSymbol } - options: z.output logger: Logger - constructor(logger: Logger, id: string, options: z.output) { + constructor( + logger: Logger, + public id: string, + public pluginOptions: z.output + ) { super() - - this.id = id - this.options = options this.logger = logger.child({ task: id }) } diff --git a/plugins/babel/src/tasks/development.ts b/plugins/babel/src/tasks/development.ts index 23e9b2465..9a3544ef0 100644 --- a/plugins/babel/src/tasks/development.ts +++ b/plugins/babel/src/tasks/development.ts @@ -6,6 +6,6 @@ export default class BabelDevelopment extends Task { static description = 'build babel' async run(): Promise { - await runBabel(this.logger, this.options) + await runBabel(this.logger, this.pluginOptions) } } diff --git a/plugins/babel/src/tasks/production.ts b/plugins/babel/src/tasks/production.ts index 8007ac9f1..d60d665ea 100644 --- a/plugins/babel/src/tasks/production.ts +++ b/plugins/babel/src/tasks/production.ts @@ -6,6 +6,6 @@ export default class BabelProduction extends Task { static description = 'build babel' async run(): Promise { - await runBabel(this.logger, this.options, { envName: 'production' }) + await runBabel(this.logger, this.pluginOptions, { envName: 'production' }) } } diff --git a/plugins/cypress/src/tasks/local.ts b/plugins/cypress/src/tasks/local.ts index 67c3e0fa1..5df26218b 100644 --- a/plugins/cypress/src/tasks/local.ts +++ b/plugins/cypress/src/tasks/local.ts @@ -8,8 +8,8 @@ import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' export default class CypressLocal extends Task { async run(): Promise { const cypressEnv: Record = {} - if (this.options.localUrl) { - cypressEnv.CYPRESS_BASE_URL = this.options.localUrl + if (this.pluginOptions.localUrl) { + cypressEnv.CYPRESS_BASE_URL = this.pluginOptions.localUrl } const doppler = new DopplerEnvVars(this.logger, 'dev') diff --git a/plugins/eslint/src/tasks/eslint.ts b/plugins/eslint/src/tasks/eslint.ts index 829a869bd..34e11e29f 100644 --- a/plugins/eslint/src/tasks/eslint.ts +++ b/plugins/eslint/src/tasks/eslint.ts @@ -8,8 +8,8 @@ export default class Eslint extends Task { static description = '' async run(files?: string[]): Promise { - const eslint = new ESLint(this.options.options) - const results = await eslint.lintFiles(files ?? this.options.files) + const eslint = new ESLint(this.pluginOptions.options) + const results = await eslint.lintFiles(files ?? this.pluginOptions.files) const formatter = await eslint.loadFormatter('stylish') const resultText = formatter.format(results) diff --git a/plugins/heroku/src/tasks/production.ts b/plugins/heroku/src/tasks/production.ts index 9249e8965..4ad84167b 100644 --- a/plugins/heroku/src/tasks/production.ts +++ b/plugins/heroku/src/tasks/production.ts @@ -20,7 +20,7 @@ export default class HerokuProduction extends Task { } const { slugId } = state - const { scaling } = this.options + const { scaling } = this.pluginOptions const scale = async () => { for (const [appName, typeConfig] of Object.entries(scaling)) { @@ -33,7 +33,7 @@ export default class HerokuProduction extends Task { } const promote = async () => { this.logger.verbose('promoting staging to production....') - await promoteStagingToProduction(this.logger, slugId, this.options.systemCode) + await promoteStagingToProduction(this.logger, slugId, this.pluginOptions.systemCode) this.logger.info('staging has been successfully promoted to production') } diff --git a/plugins/heroku/src/tasks/review.ts b/plugins/heroku/src/tasks/review.ts index 71cd4b128..c77aeba80 100644 --- a/plugins/heroku/src/tasks/review.ts +++ b/plugins/heroku/src/tasks/review.ts @@ -15,8 +15,8 @@ export default class HerokuReview extends Task { async run(): Promise { try { const pipeline = await herokuClient - .get(`/pipelines/${this.options.pipeline}`) - .catch(extractHerokuError(`getting pipeline ${this.options.pipeline}`)) + .get(`/pipelines/${this.pluginOptions.pipeline}`) + .catch(extractHerokuError(`getting pipeline ${this.pluginOptions.pipeline}`)) await setStageConfigVars(this.logger, 'review', 'prod', pipeline.id) let reviewAppId = await getHerokuReviewApp(this.logger, pipeline.id) diff --git a/plugins/heroku/src/tasks/staging.ts b/plugins/heroku/src/tasks/staging.ts index 1ffeef9bf..ec090fd5e 100644 --- a/plugins/heroku/src/tasks/staging.ts +++ b/plugins/heroku/src/tasks/staging.ts @@ -16,13 +16,13 @@ export default class HerokuStaging extends Task { async run(): Promise { try { this.logger.verbose(`retrieving pipeline details...`) - await getPipelineCouplings(this.logger, this.options.pipeline) + await getPipelineCouplings(this.logger, this.pluginOptions.pipeline) this.logger.verbose(`retrieving staging app details...`) const appName = await getHerokuStagingApp() // setting config vars on staging from the doppler production directory - await setAppConfigVars(this.logger, appName, 'prod', this.options.systemCode) + await setAppConfigVars(this.logger, appName, 'prod', this.pluginOptions.systemCode) // create build from latest commit, even on no change const buildDetails = await createBuild(this.logger, appName) diff --git a/plugins/jest/src/tasks/ci.ts b/plugins/jest/src/tasks/ci.ts index 1ed1044e8..40d6bbe32 100644 --- a/plugins/jest/src/tasks/ci.ts +++ b/plugins/jest/src/tasks/ci.ts @@ -6,6 +6,6 @@ export default class JestCI extends Task { static description = '' async run(): Promise { - await runJest(this.logger, 'ci', this.options) + await runJest(this.logger, 'ci', this.pluginOptions) } } diff --git a/plugins/jest/src/tasks/local.ts b/plugins/jest/src/tasks/local.ts index 8ecd8f470..e9441e300 100644 --- a/plugins/jest/src/tasks/local.ts +++ b/plugins/jest/src/tasks/local.ts @@ -6,6 +6,6 @@ export default class JestLocal extends Task { static description = '' async run(): Promise { - await runJest(this.logger, 'local', this.options) + await runJest(this.logger, 'local', this.pluginOptions) } } diff --git a/plugins/mocha/src/tasks/mocha.ts b/plugins/mocha/src/tasks/mocha.ts index 1eeb46709..ab7d4a9fc 100644 --- a/plugins/mocha/src/tasks/mocha.ts +++ b/plugins/mocha/src/tasks/mocha.ts @@ -10,11 +10,11 @@ export default class Mocha extends Task { static description = '' async run(): Promise { - const files = await promisify(glob)(this.options.files) + const files = await promisify(glob)(this.pluginOptions.files) const args = ['--color', ...files] - if (this.options.configPath) { - args.unshift(`--config=${this.options.configPath}`) + if (this.pluginOptions.configPath) { + args.unshift(`--config=${this.pluginOptions.configPath}`) } this.logger.info(`running mocha ${args.join(' ')}`) const child = fork(mochaCLIPath, args, { silent: true }) diff --git a/plugins/n-test/src/tasks/n-test.ts b/plugins/n-test/src/tasks/n-test.ts index 70dfd6950..b3a5240ad 100644 --- a/plugins/n-test/src/tasks/n-test.ts +++ b/plugins/n-test/src/tasks/n-test.ts @@ -14,18 +14,18 @@ export default class NTest extends Task { if (appState) { // HACK:20231003:IM keep the old logic of using the app name as the // subdomain to maintain backwards compatibility - this.options.host = + this.pluginOptions.host = 'url' in appState && appState.url ? appState.url : `https://${appState.appName}.herokuapp.com` // HACK:20231003:IM n-test naively appends paths to the host URL so // expects there to be no trailing slash - if (this.options.host.endsWith('/')) { - this.options.host = this.options.host.slice(0, -1) + if (this.pluginOptions.host.endsWith('/')) { + this.pluginOptions.host = this.pluginOptions.host.slice(0, -1) } } - const smokeTest = new SmokeTest(this.options) + const smokeTest = new SmokeTest(this.pluginOptions) this.logger.info( - `Running smoke test${this.options.host ? ` for URL ${styles.URL(this.options.host)}` : ''}` + `Running smoke test${this.pluginOptions.host ? ` for URL ${styles.URL(this.pluginOptions.host)}` : ''}` ) await smokeTest.run() } diff --git a/plugins/next-router/src/tasks/next-router.ts b/plugins/next-router/src/tasks/next-router.ts index bbeaf711a..0a5dcd247 100644 --- a/plugins/next-router/src/tasks/next-router.ts +++ b/plugins/next-router/src/tasks/next-router.ts @@ -38,7 +38,7 @@ export default class NextRouter extends Task { const unhook = hookConsole(this.logger, 'ft-next-router') try { - await register({ service: this.options.appName, port: local.port }) + await register({ service: this.pluginOptions.appName, port: local.port }) } finally { unhook() } diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index 2931dc794..f970d7bed 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -12,7 +12,7 @@ export default class Node extends Task { static description = '' async run(): Promise { - const { entry, args, useVault, ports } = this.options + const { entry, args, useVault, ports } = this.pluginOptions let vaultEnv = {} diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index b805c8c98..7160b0c9f 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -12,7 +12,7 @@ export default class Nodemon extends Task { static description = '' async run(): Promise { - const { entry, configPath, useVault, ports } = this.options + const { entry, configPath, useVault, ports } = this.pluginOptions let dopplerEnv = {} diff --git a/plugins/pa11y/src/tasks/pa11y.ts b/plugins/pa11y/src/tasks/pa11y.ts index 4d9f66962..350741bd3 100644 --- a/plugins/pa11y/src/tasks/pa11y.ts +++ b/plugins/pa11y/src/tasks/pa11y.ts @@ -19,7 +19,7 @@ export default class Pa11y extends Task { process.env.TEST_URL = `https://${reviewState.appName}.herokuapp.com` } - const args = this.options.configFile ? ['--config', this.options.configFile] : [] + const args = this.pluginOptions.configFile ? ['--config', this.pluginOptions.configFile] : [] this.logger.info(`running pa11y-ci ${args.join(' ')}`) const child = fork(pa11yCIPath, args, { silent: true }) diff --git a/plugins/prettier/src/tasks/prettier.ts b/plugins/prettier/src/tasks/prettier.ts index 4aa3779e5..cb3760089 100644 --- a/plugins/prettier/src/tasks/prettier.ts +++ b/plugins/prettier/src/tasks/prettier.ts @@ -11,11 +11,11 @@ export default class Prettier extends Task { async run(files?: string[]): Promise { try { - const filepaths = await fg(files ?? this.options.files) + const filepaths = await fg(files ?? this.pluginOptions.files) for (const filepath of filepaths) { const { ignored } = await prettier.getFileInfo(filepath) if (!ignored) { - await this.formatFile(filepath, this.options) + await this.formatFile(filepath, this.pluginOptions) } } } catch (err) { @@ -50,7 +50,7 @@ export default class Prettier extends Task { prettierConfig = options.configOptions } - const { ignored } = await prettier.getFileInfo(filepath, { ignorePath: this.options.ignoreFile }) + const { ignored } = await prettier.getFileInfo(filepath, { ignorePath: this.pluginOptions.ignoreFile }) if (ignored) { return diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index 4f982dfae..403cde8c4 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -10,7 +10,7 @@ export default class ServerlessDeploy extends Task { static description = 'Deploys on AWS' async run(): Promise { - const { useVault, configPath, buildNumVariable, regions, systemCode } = this.options + const { useVault, configPath, buildNumVariable, regions, systemCode } = this.pluginOptions const buildNum = process.env[buildNumVariable] if (buildNum === undefined) { diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index c0f8ff34a..f8b765c72 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -11,7 +11,7 @@ export default class ServerlessProvision extends Task { static description = 'Provisions a job on AWS' async run(): Promise { - const { useVault, configPath, buildNumVariable, systemCode, regions } = this.options + const { useVault, configPath, buildNumVariable, systemCode, regions } = this.pluginOptions const buildNum = process.env[buildNumVariable] if (buildNum === undefined) { diff --git a/plugins/serverless/src/tasks/run.ts b/plugins/serverless/src/tasks/run.ts index 9dc5ebc20..28a814fa7 100644 --- a/plugins/serverless/src/tasks/run.ts +++ b/plugins/serverless/src/tasks/run.ts @@ -10,7 +10,7 @@ export default class ServerlessRun extends Task { static description = 'Run serverless functions locally' async run(): Promise { - const { useVault, ports, configPath } = this.options + const { useVault, ports, configPath } = this.pluginOptions let dopplerEnv = {} diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index 64eca6cc3..adcb76303 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -11,11 +11,11 @@ export default abstract class TypeScriptTask extends Task { // TODO: add monorepo support with --build option const args = [...this.taskArgs] - if (this.options.configPath) { - args.unshift('--project', this.options.configPath) + if (this.pluginOptions.configPath) { + args.unshift('--project', this.pluginOptions.configPath) } - if (this.options.extraArgs) { - args.push(...this.options.extraArgs) + if (this.pluginOptions.extraArgs) { + args.push(...this.pluginOptions.extraArgs) } const child = fork(tscPath, args, { silent: true }) diff --git a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts index 5e687e360..4962b0d62 100644 --- a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts +++ b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts @@ -15,7 +15,7 @@ export default class UploadAssetsToS3 extends Task { - await this.uploadAssetsToS3(this.options) + await this.uploadAssetsToS3(this.pluginOptions) } async uploadFile(file: string, options: UploadAssetsToS3Options, s3: S3Client): Promise { const type = getFileType(file) diff --git a/plugins/webpack/src/tasks/development.ts b/plugins/webpack/src/tasks/development.ts index fd8b1cecc..6cb792cc6 100644 --- a/plugins/webpack/src/tasks/development.ts +++ b/plugins/webpack/src/tasks/development.ts @@ -7,7 +7,7 @@ export default class WebpackDevelopment extends Task { async run(): Promise { await runWebpack(this.logger, { - ...this.options, + ...this.pluginOptions, mode: 'development' }) } diff --git a/plugins/webpack/src/tasks/production.ts b/plugins/webpack/src/tasks/production.ts index 151465cf7..da376bba2 100644 --- a/plugins/webpack/src/tasks/production.ts +++ b/plugins/webpack/src/tasks/production.ts @@ -7,7 +7,7 @@ export default class WebpackProduction extends Task { async run(): Promise { await runWebpack(this.logger, { - ...this.options, + ...this.pluginOptions, mode: 'production' }) } diff --git a/plugins/webpack/src/tasks/watch.ts b/plugins/webpack/src/tasks/watch.ts index 97c6675ab..e026f1f5c 100644 --- a/plugins/webpack/src/tasks/watch.ts +++ b/plugins/webpack/src/tasks/watch.ts @@ -8,7 +8,7 @@ export default class WebpackWatch extends Task { async run(): Promise { // don't wait for Webpack to exit, to leave it running in the background runWebpack(this.logger, { - ...this.options, + ...this.pluginOptions, mode: 'development', watch: true }) From 995eb386ce8f475c33f7edd7645b73cb57de25f8 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Jan 2024 16:46:38 +0000 Subject: [PATCH 109/321] feat: allow tasks to receive a task options object and parse task schema when initialising --- core/cli/src/tasks.ts | 15 ++++++++++----- docs/developing-tool-kit.md | 2 +- lib/base/src/task.ts | 19 ++++++++++++++++--- lib/schemas/src/tasks.ts | 6 +++++- plugins/babel/src/tasks/development.ts | 2 +- plugins/babel/src/tasks/production.ts | 2 +- plugins/cypress/src/tasks/ci.ts | 2 +- plugins/cypress/src/tasks/local.ts | 2 +- plugins/eslint/src/tasks/eslint.ts | 2 +- plugins/heroku/src/tasks/production.ts | 2 +- plugins/heroku/src/tasks/review.ts | 2 +- plugins/heroku/src/tasks/staging.ts | 2 +- plugins/jest/src/tasks/ci.ts | 2 +- plugins/jest/src/tasks/local.ts | 2 +- plugins/mocha/src/tasks/mocha.ts | 2 +- plugins/n-test/src/tasks/n-test.ts | 2 +- plugins/next-router/src/tasks/next-router.ts | 2 +- plugins/node/src/tasks/node.ts | 2 +- plugins/nodemon/src/tasks/nodemon.ts | 2 +- plugins/pa11y/src/tasks/pa11y.ts | 2 +- plugins/prettier/src/tasks/prettier.ts | 2 +- plugins/serverless/src/tasks/deploy.ts | 2 +- plugins/serverless/src/tasks/provision.ts | 2 +- plugins/serverless/src/tasks/run.ts | 2 +- plugins/serverless/src/tasks/teardown.ts | 4 ++-- plugins/typescript/src/tasks/typescript.ts | 2 +- .../src/tasks/upload-assets-to-s3.ts | 2 +- plugins/webpack/src/tasks/development.ts | 2 +- plugins/webpack/src/tasks/production.ts | 2 +- plugins/webpack/src/tasks/watch.ts | 2 +- 30 files changed, 59 insertions(+), 37 deletions(-) diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index a3c5f0c73..782b7c2bd 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -10,6 +10,7 @@ import { checkInstall } from './install' import { styles } from '@dotcom-tool-kit/logger' import { shouldDisableNativeFetch } from './fetch' import { runInit } from './init' +import { type TaskOptions, TaskSchemas } from '@dotcom-tool-kit/schemas' type ErrorSummary = { task: string @@ -26,14 +27,18 @@ const loadTasks = async ( const entryPoint = config.tasks[taskName] const taskResult = await importEntryPoint(Task, entryPoint) - return taskResult.map((Task) => [ - taskName, - new ((Task as unknown) as TaskConstructor)( + return taskResult.map((Task) => { + const taskSchema = TaskSchemas[taskName as keyof TaskOptions] + const parsedOptions = taskSchema ? taskSchema.parse(config.taskOptions[taskName]) : {} + + const task = new ((Task as unknown) as TaskConstructor)( logger, taskName, - getOptions(entryPoint.plugin.id as OptionKey) ?? {} + getOptions(entryPoint.plugin.id as OptionKey) ?? {}, + parsedOptions ) - ]) + return [taskName, task] + }) }) ) diff --git a/docs/developing-tool-kit.md b/docs/developing-tool-kit.md index 1b6b90d8c..d3e12d2ab 100644 --- a/docs/developing-tool-kit.md +++ b/docs/developing-tool-kit.md @@ -138,7 +138,7 @@ To avoid boilerplate for tasks (the most common use case for options), when defi import { Task } from '@dotcom-tool-kit/types' import { ESLintOptions, ESLintSchema } from '@dotcom-tool-kit/schemas/lib/plugins/eslint' -export default class Eslint extends Task { +export default class Eslint extends Task<{ plugin: typeof ESLintSchema }> { static description = '' async run(): Promise { diff --git a/lib/base/src/task.ts b/lib/base/src/task.ts index 54e936ace..59a9fb92d 100644 --- a/lib/base/src/task.ts +++ b/lib/base/src/task.ts @@ -3,7 +3,14 @@ import { Base } from './base' import { taskSymbol, typeSymbol } from './symbols' import type { Logger } from 'winston' -export abstract class Task extends Base { +type Default = T extends undefined ? D : T + +export abstract class Task< + Options extends { + plugin?: z.ZodTypeAny + task?: z.ZodTypeAny + } = Record +> extends Base { static description: string static get [typeSymbol](): symbol { @@ -19,7 +26,8 @@ export abstract class Task ex constructor( logger: Logger, public id: string, - public pluginOptions: z.output + public pluginOptions: z.output>, + public options: z.output> ) { super() this.logger = logger.child({ task: id }) @@ -29,7 +37,12 @@ export abstract class Task ex } export type TaskConstructor = { - new (logger: Logger, id: string, options: Partial>): Task + new ( + logger: Logger, + id: string, + pluginOptions: Partial>, + options: Partial> + ): Task } export type TaskClass = TaskConstructor & typeof Task diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 804afcd33..3a8cf9b71 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -1,5 +1,9 @@ +import { z } from 'zod' + import { type InferSchemaOptions } from './infer' -export const TaskSchemas = {} +export const TaskSchemas = { + 'fake schema': z.never() +} export type TaskOptions = InferSchemaOptions diff --git a/plugins/babel/src/tasks/development.ts b/plugins/babel/src/tasks/development.ts index 9a3544ef0..1aed636af 100644 --- a/plugins/babel/src/tasks/development.ts +++ b/plugins/babel/src/tasks/development.ts @@ -2,7 +2,7 @@ import { runBabel } from '../run-babel' import { Task } from '@dotcom-tool-kit/base' import { BabelSchema } from '@dotcom-tool-kit/schemas/lib/plugins/babel' -export default class BabelDevelopment extends Task { +export default class BabelDevelopment extends Task<{ plugin: typeof BabelSchema }> { static description = 'build babel' async run(): Promise { diff --git a/plugins/babel/src/tasks/production.ts b/plugins/babel/src/tasks/production.ts index d60d665ea..b20a290e3 100644 --- a/plugins/babel/src/tasks/production.ts +++ b/plugins/babel/src/tasks/production.ts @@ -2,7 +2,7 @@ import { runBabel } from '../run-babel' import { Task } from '@dotcom-tool-kit/base' import { BabelSchema } from '@dotcom-tool-kit/schemas/lib/plugins/babel' -export default class BabelProduction extends Task { +export default class BabelProduction extends Task<{ plugin: typeof BabelSchema }> { static description = 'build babel' async run(): Promise { diff --git a/plugins/cypress/src/tasks/ci.ts b/plugins/cypress/src/tasks/ci.ts index 03edc3cd9..5737ec552 100644 --- a/plugins/cypress/src/tasks/ci.ts +++ b/plugins/cypress/src/tasks/ci.ts @@ -4,7 +4,7 @@ import { readState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/base' import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' -export default class CypressCi extends Task { +export default class CypressCi extends Task<{ plugin: typeof CypressSchema }> { async run(): Promise { const reviewState = readState('review') const cypressEnv: Record = {} diff --git a/plugins/cypress/src/tasks/local.ts b/plugins/cypress/src/tasks/local.ts index 5df26218b..cbdbc9454 100644 --- a/plugins/cypress/src/tasks/local.ts +++ b/plugins/cypress/src/tasks/local.ts @@ -5,7 +5,7 @@ import { readState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/base' import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' -export default class CypressLocal extends Task { +export default class CypressLocal extends Task<{ plugin: typeof CypressSchema }> { async run(): Promise { const cypressEnv: Record = {} if (this.pluginOptions.localUrl) { diff --git a/plugins/eslint/src/tasks/eslint.ts b/plugins/eslint/src/tasks/eslint.ts index 34e11e29f..7ed567fad 100644 --- a/plugins/eslint/src/tasks/eslint.ts +++ b/plugins/eslint/src/tasks/eslint.ts @@ -4,7 +4,7 @@ import { Task } from '@dotcom-tool-kit/base' import { ESLintSchema } from '@dotcom-tool-kit/schemas/lib/plugins/eslint' import { ESLint } from 'eslint' -export default class Eslint extends Task { +export default class Eslint extends Task<{ plugin: typeof ESLintSchema }> { static description = '' async run(files?: string[]): Promise { diff --git a/plugins/heroku/src/tasks/production.ts b/plugins/heroku/src/tasks/production.ts index 4ad84167b..97badffb5 100644 --- a/plugins/heroku/src/tasks/production.ts +++ b/plugins/heroku/src/tasks/production.ts @@ -8,7 +8,7 @@ import heroku, { extractHerokuError } from '../herokuClient' import { scaleDyno } from '../scaleDyno' import { promoteStagingToProduction } from '../promoteStagingToProduction' -export default class HerokuProduction extends Task { +export default class HerokuProduction extends Task<{ plugin: typeof HerokuSchema }> { static description = '' async run(): Promise { diff --git a/plugins/heroku/src/tasks/review.ts b/plugins/heroku/src/tasks/review.ts index c77aeba80..735ef1f4b 100644 --- a/plugins/heroku/src/tasks/review.ts +++ b/plugins/heroku/src/tasks/review.ts @@ -9,7 +9,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import herokuClient, { extractHerokuError } from '../herokuClient' import type { HerokuApiResPipeline } from 'heroku-client' -export default class HerokuReview extends Task { +export default class HerokuReview extends Task<{ plugin: typeof HerokuSchema }> { static description = '' async run(): Promise { diff --git a/plugins/heroku/src/tasks/staging.ts b/plugins/heroku/src/tasks/staging.ts index ec090fd5e..daa194ccc 100644 --- a/plugins/heroku/src/tasks/staging.ts +++ b/plugins/heroku/src/tasks/staging.ts @@ -10,7 +10,7 @@ import { getPipelineCouplings } from '../getPipelineCouplings' import { HerokuSchema } from '@dotcom-tool-kit/schemas/lib/plugins/heroku' import { setStagingSlug } from '../setStagingSlug' -export default class HerokuStaging extends Task { +export default class HerokuStaging extends Task<{ plugin: typeof HerokuSchema }> { static description = '' async run(): Promise { diff --git a/plugins/jest/src/tasks/ci.ts b/plugins/jest/src/tasks/ci.ts index 40d6bbe32..aa64ce927 100644 --- a/plugins/jest/src/tasks/ci.ts +++ b/plugins/jest/src/tasks/ci.ts @@ -2,7 +2,7 @@ import { Task } from '@dotcom-tool-kit/base' import { JestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/jest' import runJest from '../run-jest' -export default class JestCI extends Task { +export default class JestCI extends Task<{ plugin: typeof JestSchema }> { static description = '' async run(): Promise { diff --git a/plugins/jest/src/tasks/local.ts b/plugins/jest/src/tasks/local.ts index e9441e300..4cb4ea96a 100644 --- a/plugins/jest/src/tasks/local.ts +++ b/plugins/jest/src/tasks/local.ts @@ -2,7 +2,7 @@ import { Task } from '@dotcom-tool-kit/base' import { JestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/jest' import runJest from '../run-jest' -export default class JestLocal extends Task { +export default class JestLocal extends Task<{ plugin: typeof JestSchema }> { static description = '' async run(): Promise { diff --git a/plugins/mocha/src/tasks/mocha.ts b/plugins/mocha/src/tasks/mocha.ts index ab7d4a9fc..d309c2511 100644 --- a/plugins/mocha/src/tasks/mocha.ts +++ b/plugins/mocha/src/tasks/mocha.ts @@ -6,7 +6,7 @@ import { fork } from 'child_process' import { promisify } from 'util' const mochaCLIPath = require.resolve('mocha/bin/mocha') -export default class Mocha extends Task { +export default class Mocha extends Task<{ plugin: typeof MochaSchema }> { static description = '' async run(): Promise { diff --git a/plugins/n-test/src/tasks/n-test.ts b/plugins/n-test/src/tasks/n-test.ts index b3a5240ad..e51f830be 100644 --- a/plugins/n-test/src/tasks/n-test.ts +++ b/plugins/n-test/src/tasks/n-test.ts @@ -4,7 +4,7 @@ import { SmokeTestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/n-test' import { SmokeTest } from '@financial-times/n-test' import { readState } from '@dotcom-tool-kit/state' -export default class NTest extends Task { +export default class NTest extends Task<{ plugin: typeof SmokeTestSchema }> { static description = '' async run(): Promise { diff --git a/plugins/next-router/src/tasks/next-router.ts b/plugins/next-router/src/tasks/next-router.ts index 0a5dcd247..e0391d33a 100644 --- a/plugins/next-router/src/tasks/next-router.ts +++ b/plugins/next-router/src/tasks/next-router.ts @@ -7,7 +7,7 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { fork } from 'child_process' import { NextRouterSchema } from '@dotcom-tool-kit/schemas/lib/plugins/next-router' -export default class NextRouter extends Task { +export default class NextRouter extends Task<{ plugin: typeof NextRouterSchema }> { static description = '' async run(): Promise { diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index f970d7bed..4eaa44f55 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -8,7 +8,7 @@ import { fork } from 'child_process' import getPort from 'get-port' import waitPort from 'wait-port' -export default class Node extends Task { +export default class Node extends Task<{ plugin: typeof NodeSchema }> { static description = '' async run(): Promise { diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index 7160b0c9f..c122efb2b 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -8,7 +8,7 @@ import nodemon from 'nodemon' import { Readable } from 'stream' import { shouldDisableNativeFetch } from 'dotcom-tool-kit' -export default class Nodemon extends Task { +export default class Nodemon extends Task<{ plugin: typeof NodemonSchema }> { static description = '' async run(): Promise { diff --git a/plugins/pa11y/src/tasks/pa11y.ts b/plugins/pa11y/src/tasks/pa11y.ts index 350741bd3..fa6febb85 100644 --- a/plugins/pa11y/src/tasks/pa11y.ts +++ b/plugins/pa11y/src/tasks/pa11y.ts @@ -6,7 +6,7 @@ import { readState } from '@dotcom-tool-kit/state' const pa11yCIPath = require.resolve('pa11y-ci/bin/pa11y-ci') -export default class Pa11y extends Task { +export default class Pa11y extends Task<{ plugin: typeof Pa11ySchema }> { static description = '' async run(): Promise { diff --git a/plugins/prettier/src/tasks/prettier.ts b/plugins/prettier/src/tasks/prettier.ts index cb3760089..eccc78ac5 100644 --- a/plugins/prettier/src/tasks/prettier.ts +++ b/plugins/prettier/src/tasks/prettier.ts @@ -6,7 +6,7 @@ import { hookConsole, styles } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' import { ToolKitError } from '@dotcom-tool-kit/error' -export default class Prettier extends Task { +export default class Prettier extends Task<{ plugin: typeof PrettierSchema }> { static description = '' async run(files?: string[]): Promise { diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index 403cde8c4..861d00018 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -6,7 +6,7 @@ import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { getOptions } from '@dotcom-tool-kit/options' import { spawn } from 'child_process' -export default class ServerlessDeploy extends Task { +export default class ServerlessDeploy extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Deploys on AWS' async run(): Promise { diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index f8b765c72..2bbdb78c5 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -7,7 +7,7 @@ import { spawn } from 'child_process' import { getOptions } from '@dotcom-tool-kit/options' import { writeState } from '@dotcom-tool-kit/state' -export default class ServerlessProvision extends Task { +export default class ServerlessProvision extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Provisions a job on AWS' async run(): Promise { diff --git a/plugins/serverless/src/tasks/run.ts b/plugins/serverless/src/tasks/run.ts index 28a814fa7..df110de1a 100644 --- a/plugins/serverless/src/tasks/run.ts +++ b/plugins/serverless/src/tasks/run.ts @@ -6,7 +6,7 @@ import { hookConsole, hookFork } from '@dotcom-tool-kit/logger' import getPort from 'get-port' import waitPort from 'wait-port' -export default class ServerlessRun extends Task { +export default class ServerlessRun extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Run serverless functions locally' async run(): Promise { diff --git a/plugins/serverless/src/tasks/teardown.ts b/plugins/serverless/src/tasks/teardown.ts index 00b3a8676..db52f9b7d 100644 --- a/plugins/serverless/src/tasks/teardown.ts +++ b/plugins/serverless/src/tasks/teardown.ts @@ -7,11 +7,11 @@ import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { spawn } from 'child_process' import { getOptions } from '@dotcom-tool-kit/options' -export default class ServerlessTeardown extends Task { +export default class ServerlessTeardown extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Teardown existing serverless functions' async run(): Promise { - const { useVault, configPath, regions, systemCode } = this.options + const { useVault, configPath, regions, systemCode } = this.pluginOptions const reviewState = readState('review') diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index adcb76303..9b61db94c 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -5,7 +5,7 @@ import { fork } from 'child_process' const tscPath = require.resolve('typescript/bin/tsc') -export default abstract class TypeScriptTask extends Task { +export default abstract class TypeScriptTask extends Task<{ plugin: typeof TypeScriptSchema }> { abstract taskArgs: string[] async run(): Promise { diff --git a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts index 4962b0d62..e9e297f13 100644 --- a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts +++ b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts @@ -11,7 +11,7 @@ import { UploadAssetsToS3Schema } from '@dotcom-tool-kit/schemas/lib/plugins/upload-assets-to-s3' -export default class UploadAssetsToS3 extends Task { +export default class UploadAssetsToS3 extends Task<{ plugin: typeof UploadAssetsToS3Schema }> { static description = '' async run(): Promise { diff --git a/plugins/webpack/src/tasks/development.ts b/plugins/webpack/src/tasks/development.ts index 6cb792cc6..5b1de06a1 100644 --- a/plugins/webpack/src/tasks/development.ts +++ b/plugins/webpack/src/tasks/development.ts @@ -2,7 +2,7 @@ import { Task } from '@dotcom-tool-kit/base' import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' -export default class WebpackDevelopment extends Task { +export default class WebpackDevelopment extends Task<{ plugin: typeof WebpackSchema }> { static description = 'Run Webpack in development mode' async run(): Promise { diff --git a/plugins/webpack/src/tasks/production.ts b/plugins/webpack/src/tasks/production.ts index da376bba2..57fe1a9a9 100644 --- a/plugins/webpack/src/tasks/production.ts +++ b/plugins/webpack/src/tasks/production.ts @@ -2,7 +2,7 @@ import { Task } from '@dotcom-tool-kit/base' import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' -export default class WebpackProduction extends Task { +export default class WebpackProduction extends Task<{ plugin: typeof WebpackSchema }> { static description = 'Run Webpack in production mode' async run(): Promise { diff --git a/plugins/webpack/src/tasks/watch.ts b/plugins/webpack/src/tasks/watch.ts index e026f1f5c..c0b521ed2 100644 --- a/plugins/webpack/src/tasks/watch.ts +++ b/plugins/webpack/src/tasks/watch.ts @@ -2,7 +2,7 @@ import { Task } from '@dotcom-tool-kit/base' import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' import runWebpack from '../run-webpack' -export default class WebpackWatch extends Task { +export default class WebpackWatch extends Task<{ plugin: typeof WebpackSchema }> { static description = 'Run Webpack in watch mode in the background' async run(): Promise { From efe2e318439e870033d571b421d513a7da47a155 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Jan 2024 12:31:46 +0000 Subject: [PATCH 110/321] test: fix reference to task.options --- plugins/n-test/test/tasks/n-test.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/n-test/test/tasks/n-test.test.ts b/plugins/n-test/test/tasks/n-test.test.ts index 4546aa957..c448c2019 100644 --- a/plugins/n-test/test/tasks/n-test.test.ts +++ b/plugins/n-test/test/tasks/n-test.test.ts @@ -46,6 +46,6 @@ describe('n-test', () => { await task.run() } catch {} - expect(task.options.host).toEqual(appUrl) + expect(task.pluginOptions.host).toEqual(appUrl) }) }) From 1f6df9f5ea7f1dc0bb34bc8d567bfbeea9b94b7b Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 11:04:03 +0100 Subject: [PATCH 111/321] refactor: more specific option fallback type Co-authored-by: Ivo Murrell --- lib/base/src/task.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/base/src/task.ts b/lib/base/src/task.ts index 59a9fb92d..a8ba1763c 100644 --- a/lib/base/src/task.ts +++ b/lib/base/src/task.ts @@ -26,8 +26,8 @@ export abstract class Task< constructor( logger: Logger, public id: string, - public pluginOptions: z.output>, - public options: z.output> + public pluginOptions: z.output>>>, + public options: z.output>>> ) { super() this.logger = logger.child({ task: id }) From 4e6caea404d07798ea14f0dea599fb08cb9ca601 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 11:05:26 +0100 Subject: [PATCH 112/321] feat: validate task option conflicts and unused task options --- core/cli/src/config.ts | 39 ++++++++++++++++++++++++-------- core/cli/src/messages.ts | 49 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index c9ae5b10d..5df9ee99a 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -13,12 +13,14 @@ import { RawConfig, ValidConfig, ValidPluginsConfig } from '@dotcom-tool-kit/con import { formatTaskConflicts, formatUndefinedCommandTasks, - formatUnusedOptions, + formatUnusedPluginOptions, formatCommandTaskConflicts, formatHookConflicts, - formatOptionConflicts, + formatPluginOptionConflicts, formatMissingTasks, - formatInvalidOptions + formatInvalidOptions, + formatTaskOptionConflicts, + formatUnusedTaskOptions } from './messages' import { validatePlugins } from './config/validate-plugins' import { validatePluginOptions } from './plugin/options' @@ -43,7 +45,8 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali const commandTaskConflicts = findConflicts(Object.values(config.commandTasks)) const hookConflicts = findConflictingEntries(config.hooks) const taskConflicts = findConflictingEntries(config.tasks) - const optionConflicts = findConflicts(Object.values(config.pluginOptions)) + const pluginOptionConflicts = findConflicts(Object.values(config.pluginOptions)) + const taskOptionConflicts = findConflicts(Object.values(config.taskOptions)) const definedCommandTaskConflicts = commandTaskConflicts.filter((conflict) => { return conflict.conflicting[0].id in config.hooks @@ -65,7 +68,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali hookConflicts.length > 0 || definedCommandTaskConflicts.length > 0 || taskConflicts.length > 0 || - optionConflicts.length > 0 + pluginOptionConflicts.length > 0 ) { shouldThrow = true @@ -81,8 +84,12 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali error.details += formatTaskConflicts(taskConflicts) } - if (optionConflicts.length) { - error.details += formatOptionConflicts(optionConflicts) + if (pluginOptionConflicts.length) { + error.details += formatPluginOptionConflicts(pluginOptionConflicts) + } + + if (taskOptionConflicts.length) { + error.details += formatTaskOptionConflicts(taskOptionConflicts) } } @@ -108,15 +115,27 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali error.details += formatInvalidOptions(invalidOptions) } - const unusedOptions = Object.entries(config.pluginOptions) + const unusedPluginOptions = Object.entries(config.pluginOptions) .filter( ([, option]) => option && !isConflict(option) && !option.forPlugin && option.plugin.root === process.cwd() ) .map(([id]) => id) - if (unusedOptions.length > 0) { + + if (unusedPluginOptions.length > 0) { + shouldThrow = true + error.details += formatUnusedPluginOptions(unusedPluginOptions, Object.keys(config.plugins)) + } + + const unusedTaskOptions = Object.entries(config.taskOptions) + .filter( + ([, option]) => option && !isConflict(option) && !option.task && option.plugin.root === process.cwd() + ) + .map(([id]) => id) + + if (unusedTaskOptions.length > 0) { shouldThrow = true - error.details += formatUnusedOptions(unusedOptions, Object.keys(config.plugins)) + error.details += formatUnusedTaskOptions(unusedTaskOptions, Object.keys(config.tasks)) } const missingTasks = configuredCommandTasks diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 4375bcc20..fceab661e 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -1,6 +1,12 @@ import { styles as s, styles } from '@dotcom-tool-kit/logger' import type { Hook } from '@dotcom-tool-kit/base' -import type { CommandTask, EntryPoint, Plugin, OptionsForPlugin } from '@dotcom-tool-kit/plugin' +import type { + CommandTask, + EntryPoint, + Plugin, + OptionsForPlugin, + OptionsForTask +} from '@dotcom-tool-kit/plugin' import type { z } from 'zod' import { fromZodError } from 'zod-validation-error' import type { Conflict } from '@dotcom-tool-kit/conflict' @@ -50,16 +56,16 @@ You must resolve this conflict by explicitly configuring which task to run for t ` -const formatOptionConflict = (conflict: Conflict): string => `${s.plugin( +const formatPluginOptionConflict = (conflict: Conflict): string => `${s.plugin( conflict.conflicting[0].forPlugin.id )}, configured by: ${conflict.conflicting.map((option) => `- ${s.plugin(option.plugin.id)}`)}` -export const formatOptionConflicts = (conflicts: Conflict[]): string => `${s.heading( +export const formatPluginOptionConflicts = (conflicts: Conflict[]): string => `${s.heading( 'These plugins have conflicting options' )}: -${conflicts.map(formatOptionConflict).join('\n')} +${conflicts.map(formatPluginOptionConflict).join('\n')} You must resolve this conflict by providing options in your app's Tool Kit configuration for these plugins, or installing a use-case plugin that provides these options. See ${s.URL( 'https://github.com/financial-times/dotcom-tool-kit/tree/main/readme.md#options' @@ -67,6 +73,23 @@ You must resolve this conflict by providing options in your app's Tool Kit confi ` +const formatTaskOptionConflict = (conflict: Conflict): string => `${s.task( + conflict.conflicting[0].task +)}, configured by: +${conflict.conflicting.map((option) => `- ${s.plugin(option.plugin.id)}`)}` + +export const formatTaskOptionConflicts = (conflicts: Conflict[]): string => `${s.heading( + 'These tasks have conflicting options' +)}: + +${conflicts.map(formatTaskOptionConflict).join('\n')} + +You must resolve this conflict by providing options in your app's Tool Kit configuration for these tasks, or installing a use-case plugin that provides these options. See ${s.URL( + 'https://github.com/financial-times/dotcom-tool-kit/tree/main/readme.md#options' +)} for more details. + +` + const formatPlugin = (plugin: Plugin): string => plugin.id === 'app root' ? s.app('your app') : `plugin ${s.plugin(plugin.id)}` @@ -100,7 +123,7 @@ ${invalidOptions Please update the options so that they are the expected types. You can refer to the README for the plugin for examples and descriptions of the options used. ` -export const formatUnusedOptions = ( +export const formatUnusedPluginOptions = ( unusedOptions: string[], definedPlugins: string[] ): string => `Options are defined in your Tool Kit configuration for plugins that don't exist: @@ -116,6 +139,22 @@ ${ }. ` +export const formatUnusedTaskOptions = ( + unusedOptions: string[], + definedTasks: string[] +): string => `Options are defined in your Tool Kit configuration for tasks that don't exist: + +${unusedOptions.map((optionName) => `- ${s.task(optionName)}`).join('\n')} + +They could be misspelt, or defined by a Tool Kit plugin that isn't installed in this app. + +${ + definedTasks.length > 0 + ? `Task that are defined and can have options set are: ${definedTasks.map(s.task).join(', ')}` + : `You don't have currently any plugins installed that provide tasks. You'll need to install some plugins before options can be set.` +}. +` + export const formatUninstalledHooks = ( uninstalledHooks: Hook[] ): string => `These hooks aren't installed into your app: From 27b5783fcbab9df2018757f4ea06178ceac74c78 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 11:35:06 +0100 Subject: [PATCH 113/321] fix: remove conflicts from task options in valid config type --- core/cli/src/tasks.ts | 10 ++++++---- lib/config/src/index.ts | 14 +++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 782b7c2bd..62b687537 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -19,7 +19,7 @@ type ErrorSummary = { const loadTasks = async ( logger: Logger, - taskNames: string[], + taskNames: (keyof TaskOptions)[], config: ValidConfig ): Promise>> => { const taskResults = await Promise.all( @@ -28,10 +28,10 @@ const loadTasks = async ( const taskResult = await importEntryPoint(Task, entryPoint) return taskResult.map((Task) => { - const taskSchema = TaskSchemas[taskName as keyof TaskOptions] + const taskSchema = TaskSchemas[taskName] const parsedOptions = taskSchema ? taskSchema.parse(config.taskOptions[taskName]) : {} - const task = new ((Task as unknown) as TaskConstructor)( + const task = new (Task as unknown as TaskConstructor)( logger, taskName, getOptions(entryPoint.plugin.id as OptionKey) ?? {}, @@ -78,7 +78,9 @@ ${availableCommands}` process.execArgv.push('--no-experimental-fetch') } - const taskNames = commands.flatMap((command) => config.commandTasks[command]?.tasks ?? []) + const taskNames = commands.flatMap( + (command) => config.commandTasks[command]?.tasks ?? [] + ) as (keyof TaskOptions)[] const tasks = (await loadTasks(logger, taskNames, config)).unwrap('tasks are invalid') for (const command of commands) { diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts index 91d99eb26..e82761b20 100644 --- a/lib/config/src/index.ts +++ b/lib/config/src/index.ts @@ -25,17 +25,21 @@ export type ValidPluginsConfig = Omit & { plugins: { [id: string]: Plugin } } -export type ValidPluginOptions = Omit & { +export type ValidOptionsForPlugin = Omit & { options: PluginOptions[Id] } -export type ValidOptions = { - [Id in keyof PluginOptions]: ValidPluginOptions +export type ValidPluginOptions = { + [Id in keyof PluginOptions]: ValidOptionsForPlugin } -export type ValidConfig = Omit & { +export type ValidConfig = Omit< + ValidPluginsConfig, + 'tasks' | 'commandTasks' | 'pluginOptions' | 'taskOptions' | 'hooks' +> & { tasks: { [id: string]: EntryPoint } commandTasks: { [id: string]: CommandTask } - pluginOptions: ValidOptions + pluginOptions: ValidPluginOptions + taskOptions: { [id: string]: OptionsForTask } hooks: { [id: string]: EntryPoint } } From 2b0ccadcdc8e5ffb773b84c3ae4aedf31a75c4d1 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:41:51 +0100 Subject: [PATCH 114/321] fix: throw if there are task option conflicts Co-authored-by: Ivo Murrell --- core/cli/src/config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 5df9ee99a..48ae1cf3d 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -68,7 +68,8 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali hookConflicts.length > 0 || definedCommandTaskConflicts.length > 0 || taskConflicts.length > 0 || - pluginOptionConflicts.length > 0 + pluginOptionConflicts.length > 0 || + taskOptionConflicts.length > 0 ) { shouldThrow = true From 2f0c2b68e6668fdbcc14c88458243f7377eefe39 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 09:23:32 +0100 Subject: [PATCH 115/321] feat!: load hook installations from options.hooks --- core/cli/src/plugin/reduce-installations.ts | 4 ++-- core/cli/src/rc-file.ts | 13 ++++++++----- core/create/src/index.ts | 11 ++++++----- lib/plugin/src/index.ts | 3 ++- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/core/cli/src/plugin/reduce-installations.ts b/core/cli/src/plugin/reduce-installations.ts index 614994417..c629c3283 100644 --- a/core/cli/src/plugin/reduce-installations.ts +++ b/core/cli/src/plugin/reduce-installations.ts @@ -56,11 +56,11 @@ export async function reducePluginHookInstallations( return hookClass.mergeChildInstallations(plugin, installations) }) - if (plugin.rcFile.hooks.length === 0) { + if (plugin.rcFile.options.hooks.length === 0) { return childInstallations } - return plugin.rcFile.hooks.flatMap((hookEntry) => + return plugin.rcFile.options.hooks.flatMap((hookEntry) => Object.entries(hookEntry).flatMap(([id, configHookOptions]) => { const hookClass = hookClasses[id] const parsedOptions = HookSchemas[id as keyof HookOptions].parse(configHookOptions) diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 5e7d53c55..4c3e57b42 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -10,8 +10,7 @@ const emptyConfig = { installs: {}, tasks: {}, commands: {}, - options: { plugins: {}, tasks: {} }, - hooks: [], + options: { plugins: {}, tasks: {}, hooks: [] }, init: [] } satisfies RCFile let rootConfig: string | undefined @@ -51,9 +50,13 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo tasks: config.tasks ?? {}, commands: config.commands ?? {}, options: config.options - ? { plugins: config.options.plugins ?? {}, tasks: config.options.tasks ?? {} } - : { plugins: {}, tasks: {} }, - hooks: config.hooks ?? [], + ? { + plugins: config.options.plugins ?? {}, + tasks: config.options.tasks ?? {}, + hooks: config.options.hooks ?? [] + } + : { plugins: {}, tasks: {}, hooks: [] }, + hooks: config.hooks ?? undefined, init: config.init ?? [] } } diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 5c7442815..639414f20 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -47,9 +47,11 @@ function getEslintConfigContent(): string { function clearConfigCache() { // we need to import explorer from the app itself instead of npx as this is // the object used by installHooks() - return (importCwd('dotcom-tool-kit/lib/rc-file') as { - explorer: ReturnType - }).explorer.clearSearchCache() + return ( + importCwd('dotcom-tool-kit/lib/rc-file') as { + explorer: ReturnType + } + ).explorer.clearSearchCache() } async function executeMigration( @@ -116,8 +118,7 @@ async function main() { installs: {}, tasks: {}, commands: {}, - options: { plugins: {}, tasks: {} }, - hooks: [], + options: { plugins: {}, tasks: {}, hooks: [] }, init: [] } diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts index 0cc0830ef..f9343e671 100644 --- a/lib/plugin/src/index.ts +++ b/lib/plugin/src/index.ts @@ -3,11 +3,12 @@ export type RCFile = { installs: { [id: string]: string } tasks: { [id: string]: string } commands: { [id: string]: string | string[] } + hooks?: { [id: string]: string | string[] } options: { plugins: { [id: string]: Record } tasks: { [id: string]: Record } + hooks: { [id: string]: Record }[] } - hooks: { [id: string]: Record }[] init: string[] } From 75ed6f414dfb42b4feb132e66481d5ba20629445 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 09:29:15 +0100 Subject: [PATCH 116/321] feat: load hooks in toolkitrc as commands and warn about it --- core/cli/src/plugin.ts | 2 +- core/cli/src/plugin/merge-commands.ts | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 3ad455bc9..8efdd6a47 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -77,7 +77,7 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger mergeTasks(config, plugin) mergeHooks(config, plugin) - mergeCommands(config, plugin) + mergeCommands(config, plugin, logger) mergePluginOptions(config, plugin) mergeTaskOptions(config, plugin) mergeInits(config, plugin) diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts index c63bd4f2c..978890d24 100644 --- a/core/cli/src/plugin/merge-commands.ts +++ b/core/cli/src/plugin/merge-commands.ts @@ -2,10 +2,24 @@ import type { CommandTask, Plugin } from '@dotcom-tool-kit/plugin' import type { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { isDescendent } from './is-descendent' +import { Logger } from 'winston' +import { styles as s } from '@dotcom-tool-kit/logger' +import path from 'path' -export const mergeCommands = (config: ValidPluginsConfig, plugin: Plugin) => { +export const mergeCommands = (config: ValidPluginsConfig, plugin: Plugin, logger: Logger) => { if (plugin.rcFile) { - for (const [id, configCommandTask] of Object.entries(plugin.rcFile.commands)) { + let commands = plugin.rcFile.commands + + if (plugin.rcFile.hooks) { + commands = plugin.rcFile.hooks + logger.warn( + `${s.code('hooks')} is deprecated in ${s.filepath('.toolkitrc.yml')}. please rename ${s.code( + 'hooks' + )} to ${s.code('commands')} in ${s.filepath(path.join(plugin.root, '.toolkitrc.yml'))}.` + ) + } + + for (const [id, configCommandTask] of Object.entries(commands)) { // handle conflicts between commands from different plugins const existingCommandTask = config.commandTasks[id] const newCommandTask: CommandTask = { From 8ae4f6a1c916ea696f5696de744f7b2ecc4c2777 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 11:31:26 +0100 Subject: [PATCH 117/321] docs: add todo comment to remove legacy handling in future major --- core/cli/src/plugin/merge-commands.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts index 978890d24..72715caa0 100644 --- a/core/cli/src/plugin/merge-commands.ts +++ b/core/cli/src/plugin/merge-commands.ts @@ -10,6 +10,8 @@ export const mergeCommands = (config: ValidPluginsConfig, plugin: Plugin, logger if (plugin.rcFile) { let commands = plugin.rcFile.commands + // TODO:KB:20240410 remove this legacy hooks field handling and the associated + // field in the type definitions in a future major version if (plugin.rcFile.hooks) { commands = plugin.rcFile.hooks logger.warn( From 34d28e66db69f59882c64bfb3f4d28efc9bda7cd Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 10:57:44 +0100 Subject: [PATCH 118/321] feat: allow loading old-style options fields with a warning --- core/cli/src/rc-file.ts | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 4c3e57b42..6ef275a12 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -18,9 +18,11 @@ let rootConfig: string | undefined type RawRCFile = { [key in Exclude]?: RCFile[key] | null } & { - options: { - [key in keyof RCFile['options']]?: RCFile['options'][key] | null - } + options: + | { + [key in keyof RCFile['options']]?: RCFile['options'][key] | null + } + | null } export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boolean): Promise { @@ -44,6 +46,27 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo } const config: RawRCFile = result.config + + // if a toolkitrc contains a non-empty options field, but not options.{plugins,tasks,hooks}, + // assume it's an old-style, plugins-only options field. + if ( + config.options && + Object.keys(config.options).length > 0 && + !(config.options.plugins || config.options.tasks || config.options.hooks) + ) { + config.options = { + plugins: config.options as { [id: string]: Record } + } + + logger.warn( + `plugin at ${s.filepath(path.dirname(root))} has an ${s.code( + 'options' + )} field that only contains plugin options. these options should be moved to ${s.code( + 'options.plugins' + )}.` + ) + } + return { plugins: config.plugins ?? [], installs: config.installs ?? {}, From 601585634f83de9101c21b757bc3e673b0e4733e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 11:32:32 +0100 Subject: [PATCH 119/321] docs: add todo comment to remove legacy handling in future major --- core/cli/src/rc-file.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 6ef275a12..23ff339b4 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -49,6 +49,7 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo // if a toolkitrc contains a non-empty options field, but not options.{plugins,tasks,hooks}, // assume it's an old-style, plugins-only options field. + // TODO:KB:20240410 remove this legacy options field handling in a future major version if ( config.options && Object.keys(config.options).length > 0 && From 3c987609092a629e3000b43f8c5fdb4592ffc789 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 10:15:15 +0100 Subject: [PATCH 120/321] feat!: only load plugins if their toolkitrc version matches the current version --- core/cli/src/plugin.ts | 12 +++++++++++- core/cli/src/rc-file.ts | 1 + lib/plugin/src/index.ts | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 8efdd6a47..0b167bde4 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -1,5 +1,5 @@ import { styles as s } from '@dotcom-tool-kit/logger' -import type { Plugin } from '@dotcom-tool-kit/plugin' +import { CURRENT_RC_FILE_VERSION, type Plugin } from '@dotcom-tool-kit/plugin' import type { RawConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' import { invalid, reduceValidated, valid, Validated } from '@dotcom-tool-kit/validated' import resolvePkg from 'resolve-pkg' @@ -41,6 +41,16 @@ export async function loadPlugin( children: [] as Plugin[] } + if (!isAppRoot && plugin.rcFile.version !== CURRENT_RC_FILE_VERSION) { + return invalid([ + `plugin ${s.plugin(id)} has a v${s.code((plugin.rcFile.version ?? 1).toString())} ${s.code( + '.toolkitrc.yml' + )}, but this version of Tool Kit can only load v${s.code( + CURRENT_RC_FILE_VERSION.toString() + )}. please update this plugin.` + ]) + } + // ESlint disable explanation: erroring due to a possible race condition but is a false positive since the config variable isn't from another scope and can't be written to concurrently. // eslint-disable-next-line require-atomic-updates config.plugins[id] = valid(plugin) diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 23ff339b4..b1fa2eec1 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -69,6 +69,7 @@ export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boo } return { + version: config.version ?? undefined, plugins: config.plugins ?? [], installs: config.installs ?? {}, tasks: config.tasks ?? {}, diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts index f9343e671..696fc3c0a 100644 --- a/lib/plugin/src/index.ts +++ b/lib/plugin/src/index.ts @@ -1,4 +1,7 @@ +export const CURRENT_RC_FILE_VERSION = 2 + export type RCFile = { + version?: typeof CURRENT_RC_FILE_VERSION plugins: string[] installs: { [id: string]: string } tasks: { [id: string]: string } From a49c1aa01916ca8afee5935d1ef28856a6814042 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 10:33:52 +0100 Subject: [PATCH 121/321] chore: add versions to all plugin toolkitrcs --- core/cli/test/files/conflict-resolution/.toolkitrc.yml | 2 ++ core/cli/test/files/conflicted/.toolkitrc.yml | 2 ++ core/cli/test/files/cousins/.toolkitrc.yml | 2 ++ core/cli/test/files/duplicate/.toolkitrc.yml | 2 ++ core/cli/test/files/successful/.toolkitrc.yml | 2 ++ lib/doppler/.toolkitrc.yml | 2 ++ lib/options/.toolkitrc.yml | 2 ++ lib/vault/.toolkitrc.yml | 2 ++ plugins/babel/.toolkitrc.yml | 2 ++ plugins/backend-app/.toolkitrc.yml | 2 ++ plugins/backend-heroku-app/.toolkitrc.yml | 2 ++ plugins/backend-serverless-app/.toolkitrc.yml | 2 ++ plugins/circleci-deploy/.toolkitrc.yml | 2 ++ plugins/circleci-heroku/.toolkitrc.yml | 2 ++ plugins/circleci-npm/.toolkitrc.yml | 2 ++ plugins/circleci/.toolkitrc.yml | 2 ++ plugins/component/.toolkitrc.yml | 2 ++ plugins/cypress/.toolkitrc.yml | 2 ++ plugins/eslint/.toolkitrc.yml | 2 ++ plugins/frontend-app/.toolkitrc.yml | 2 ++ plugins/heroku/.toolkitrc.yml | 2 ++ plugins/husky-npm/.toolkitrc.yml | 2 ++ plugins/jest/.toolkitrc.yml | 2 ++ plugins/lint-staged-npm/.toolkitrc.yml | 2 ++ plugins/lint-staged/.toolkitrc.yml | 2 ++ plugins/mocha/.toolkitrc.yml | 2 ++ plugins/n-test/.toolkitrc.yml | 2 ++ plugins/next-router/.toolkitrc.yml | 2 ++ plugins/node/.toolkitrc.yml | 2 ++ plugins/nodemon/.toolkitrc.yml | 2 ++ plugins/npm/.toolkitrc.yml | 2 ++ plugins/pa11y/.toolkitrc.yml | 2 ++ plugins/package-json-hook/.toolkitrc.yml | 2 ++ plugins/prettier/.toolkitrc.yml | 2 ++ plugins/serverless/.toolkitrc.yml | 2 ++ plugins/typescript/.toolkitrc.yml | 2 ++ plugins/upload-assets-to-s3/.toolkitrc.yml | 2 ++ plugins/webpack/.toolkitrc.yml | 2 ++ 38 files changed, 76 insertions(+) diff --git a/core/cli/test/files/conflict-resolution/.toolkitrc.yml b/core/cli/test/files/conflict-resolution/.toolkitrc.yml index 4bf53682e..e0dd83e80 100644 --- a/core/cli/test/files/conflict-resolution/.toolkitrc.yml +++ b/core/cli/test/files/conflict-resolution/.toolkitrc.yml @@ -28,3 +28,5 @@ commands: build:remote: - WebpackProduction - BabelProduction + +version: 2 diff --git a/core/cli/test/files/conflicted/.toolkitrc.yml b/core/cli/test/files/conflicted/.toolkitrc.yml index 273807168..fa591e1a6 100644 --- a/core/cli/test/files/conflicted/.toolkitrc.yml +++ b/core/cli/test/files/conflicted/.toolkitrc.yml @@ -7,3 +7,5 @@ plugins: options: commands: + +version: 2 diff --git a/core/cli/test/files/cousins/.toolkitrc.yml b/core/cli/test/files/cousins/.toolkitrc.yml index 88834875f..6d9e095f4 100644 --- a/core/cli/test/files/cousins/.toolkitrc.yml +++ b/core/cli/test/files/cousins/.toolkitrc.yml @@ -7,3 +7,5 @@ plugins: options: commands: + +version: 2 diff --git a/core/cli/test/files/duplicate/.toolkitrc.yml b/core/cli/test/files/duplicate/.toolkitrc.yml index 3b29e8687..0bebeb564 100644 --- a/core/cli/test/files/duplicate/.toolkitrc.yml +++ b/core/cli/test/files/duplicate/.toolkitrc.yml @@ -17,3 +17,5 @@ options: app: tool-kit-test commands: + +version: 2 diff --git a/core/cli/test/files/successful/.toolkitrc.yml b/core/cli/test/files/successful/.toolkitrc.yml index abceebdcc..369899e0d 100644 --- a/core/cli/test/files/successful/.toolkitrc.yml +++ b/core/cli/test/files/successful/.toolkitrc.yml @@ -21,3 +21,5 @@ commands: 'test:ci': - Mocha - Eslint + +version: 2 diff --git a/lib/doppler/.toolkitrc.yml b/lib/doppler/.toolkitrc.yml index 0abc882df..672166f4d 100644 --- a/lib/doppler/.toolkitrc.yml +++ b/lib/doppler/.toolkitrc.yml @@ -1,2 +1,4 @@ plugins: - '@dotcom-tool-kit/vault' + +version: 2 diff --git a/lib/options/.toolkitrc.yml b/lib/options/.toolkitrc.yml index e69de29bb..d48cfb24d 100644 --- a/lib/options/.toolkitrc.yml +++ b/lib/options/.toolkitrc.yml @@ -0,0 +1,2 @@ + +version: 2 diff --git a/lib/vault/.toolkitrc.yml b/lib/vault/.toolkitrc.yml index e69de29bb..d48cfb24d 100644 --- a/lib/vault/.toolkitrc.yml +++ b/lib/vault/.toolkitrc.yml @@ -0,0 +1,2 @@ + +version: 2 diff --git a/plugins/babel/.toolkitrc.yml b/plugins/babel/.toolkitrc.yml index cd4388afc..8f5d2558f 100644 --- a/plugins/babel/.toolkitrc.yml +++ b/plugins/babel/.toolkitrc.yml @@ -6,3 +6,5 @@ commands: 'build:local': BabelDevelopment 'build:ci': BabelProduction 'build:remote': BabelProduction + +version: 2 diff --git a/plugins/backend-app/.toolkitrc.yml b/plugins/backend-app/.toolkitrc.yml index 08ec2cb27..17d4d01f7 100644 --- a/plugins/backend-app/.toolkitrc.yml +++ b/plugins/backend-app/.toolkitrc.yml @@ -1,2 +1,4 @@ plugins: - '@dotcom-tool-kit/backend-heroku-app' + +version: 2 diff --git a/plugins/backend-heroku-app/.toolkitrc.yml b/plugins/backend-heroku-app/.toolkitrc.yml index cc31d2c1c..ec0dd8ed0 100644 --- a/plugins/backend-heroku-app/.toolkitrc.yml +++ b/plugins/backend-heroku-app/.toolkitrc.yml @@ -10,3 +10,5 @@ commands: 'deploy:staging': HerokuStaging 'deploy:production': HerokuProduction 'teardown:staging': HerokuTeardown + +version: 2 diff --git a/plugins/backend-serverless-app/.toolkitrc.yml b/plugins/backend-serverless-app/.toolkitrc.yml index d5c102f11..3ac88b102 100644 --- a/plugins/backend-serverless-app/.toolkitrc.yml +++ b/plugins/backend-serverless-app/.toolkitrc.yml @@ -9,3 +9,5 @@ commands: 'deploy:review': ServerlessProvision 'deploy:production': ServerlessDeploy 'teardown:review': ServerlessTeardown + +version: 2 diff --git a/plugins/circleci-deploy/.toolkitrc.yml b/plugins/circleci-deploy/.toolkitrc.yml index 067c53577..7a8faa61f 100644 --- a/plugins/circleci-deploy/.toolkitrc.yml +++ b/plugins/circleci-deploy/.toolkitrc.yml @@ -1,2 +1,4 @@ plugins: - '@dotcom-tool-kit/circleci' + +version: 2 diff --git a/plugins/circleci-heroku/.toolkitrc.yml b/plugins/circleci-heroku/.toolkitrc.yml index 480dbe296..332016f76 100644 --- a/plugins/circleci-heroku/.toolkitrc.yml +++ b/plugins/circleci-heroku/.toolkitrc.yml @@ -7,3 +7,5 @@ commands: 'deploy:staging': HerokuStaging 'deploy:production': HerokuProduction 'teardown:staging': HerokuTeardown + +version: 2 diff --git a/plugins/circleci-npm/.toolkitrc.yml b/plugins/circleci-npm/.toolkitrc.yml index 9483399bc..fd7b8e187 100644 --- a/plugins/circleci-npm/.toolkitrc.yml +++ b/plugins/circleci-npm/.toolkitrc.yml @@ -4,3 +4,5 @@ plugins: commands: 'publish:tag': NpmPublish + +version: 2 diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index eaa915321..9bc57a6dc 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -3,3 +3,5 @@ installs: init: - './lib/init-env-vars' + +version: 2 diff --git a/plugins/component/.toolkitrc.yml b/plugins/component/.toolkitrc.yml index b01fd7dc6..a5419d57e 100644 --- a/plugins/component/.toolkitrc.yml +++ b/plugins/component/.toolkitrc.yml @@ -1,3 +1,5 @@ plugins: - '@dotcom-tool-kit/npm' - '@dotcom-tool-kit/circleci-npm' + +version: 2 diff --git a/plugins/cypress/.toolkitrc.yml b/plugins/cypress/.toolkitrc.yml index 92cd32fbe..dc8e7c03b 100644 --- a/plugins/cypress/.toolkitrc.yml +++ b/plugins/cypress/.toolkitrc.yml @@ -6,3 +6,5 @@ commands: 'test:review': CypressCi 'test:staging': CypressCi 'e2e:local': CypressLocal + +version: 2 diff --git a/plugins/eslint/.toolkitrc.yml b/plugins/eslint/.toolkitrc.yml index e74177acc..1662d032b 100644 --- a/plugins/eslint/.toolkitrc.yml +++ b/plugins/eslint/.toolkitrc.yml @@ -5,3 +5,5 @@ commands: 'test:local': Eslint 'test:ci': Eslint 'test:staged': Eslint + +version: 2 diff --git a/plugins/frontend-app/.toolkitrc.yml b/plugins/frontend-app/.toolkitrc.yml index f476a469c..d5e4ccbdd 100644 --- a/plugins/frontend-app/.toolkitrc.yml +++ b/plugins/frontend-app/.toolkitrc.yml @@ -8,3 +8,5 @@ commands: - WebpackDevelopment # run a webpack compile before starting the server because dotcom-server-asset-loader expects a manifest to exist - Node - WebpackWatch + +version: 2 diff --git a/plugins/heroku/.toolkitrc.yml b/plugins/heroku/.toolkitrc.yml index bd7a8023f..fe2de5724 100644 --- a/plugins/heroku/.toolkitrc.yml +++ b/plugins/heroku/.toolkitrc.yml @@ -10,3 +10,5 @@ tasks: commands: 'cleanup:remote': NpmPrune + +version: 2 diff --git a/plugins/husky-npm/.toolkitrc.yml b/plugins/husky-npm/.toolkitrc.yml index e69de29bb..d48cfb24d 100644 --- a/plugins/husky-npm/.toolkitrc.yml +++ b/plugins/husky-npm/.toolkitrc.yml @@ -0,0 +1,2 @@ + +version: 2 diff --git a/plugins/jest/.toolkitrc.yml b/plugins/jest/.toolkitrc.yml index 279f39daf..46d3ab103 100644 --- a/plugins/jest/.toolkitrc.yml +++ b/plugins/jest/.toolkitrc.yml @@ -5,3 +5,5 @@ tasks: commands: 'test:local': JestLocal 'test:ci': JestCI + +version: 2 diff --git a/plugins/lint-staged-npm/.toolkitrc.yml b/plugins/lint-staged-npm/.toolkitrc.yml index 03647dfa9..cba1ca086 100644 --- a/plugins/lint-staged-npm/.toolkitrc.yml +++ b/plugins/lint-staged-npm/.toolkitrc.yml @@ -1,3 +1,5 @@ plugins: - '@dotcom-tool-kit/lint-staged' - '@dotcom-tool-kit/husky-npm' + +version: 2 diff --git a/plugins/lint-staged/.toolkitrc.yml b/plugins/lint-staged/.toolkitrc.yml index ba50cab20..0efc6ac03 100644 --- a/plugins/lint-staged/.toolkitrc.yml +++ b/plugins/lint-staged/.toolkitrc.yml @@ -3,3 +3,5 @@ tasks: commands: 'git:precommit': LintStaged + +version: 2 diff --git a/plugins/mocha/.toolkitrc.yml b/plugins/mocha/.toolkitrc.yml index 678446b2d..0c788aeb6 100644 --- a/plugins/mocha/.toolkitrc.yml +++ b/plugins/mocha/.toolkitrc.yml @@ -4,3 +4,5 @@ tasks: commands: 'test:local': Mocha 'test:ci': Mocha + +version: 2 diff --git a/plugins/n-test/.toolkitrc.yml b/plugins/n-test/.toolkitrc.yml index 450a496d0..723cf56c4 100644 --- a/plugins/n-test/.toolkitrc.yml +++ b/plugins/n-test/.toolkitrc.yml @@ -4,3 +4,5 @@ tasks: commands: 'test:review': NTest 'test:staging': NTest + +version: 2 diff --git a/plugins/next-router/.toolkitrc.yml b/plugins/next-router/.toolkitrc.yml index 137fc6d9f..c18468860 100644 --- a/plugins/next-router/.toolkitrc.yml +++ b/plugins/next-router/.toolkitrc.yml @@ -7,3 +7,5 @@ tasks: commands: run:local: - NextRouter + +version: 2 diff --git a/plugins/node/.toolkitrc.yml b/plugins/node/.toolkitrc.yml index 32968f1d0..5e2203766 100644 --- a/plugins/node/.toolkitrc.yml +++ b/plugins/node/.toolkitrc.yml @@ -6,3 +6,5 @@ tasks: commands: 'run:local': Node + +version: 2 diff --git a/plugins/nodemon/.toolkitrc.yml b/plugins/nodemon/.toolkitrc.yml index 9eb48e671..5611627df 100644 --- a/plugins/nodemon/.toolkitrc.yml +++ b/plugins/nodemon/.toolkitrc.yml @@ -6,3 +6,5 @@ tasks: commands: 'run:local': Nodemon + +version: 2 diff --git a/plugins/npm/.toolkitrc.yml b/plugins/npm/.toolkitrc.yml index 84bb831cb..148e1b399 100644 --- a/plugins/npm/.toolkitrc.yml +++ b/plugins/npm/.toolkitrc.yml @@ -1,3 +1,5 @@ tasks: NpmPrune: './lib/tasks/prune' NpmPublish: './lib/tasks/publish' + +version: 2 diff --git a/plugins/pa11y/.toolkitrc.yml b/plugins/pa11y/.toolkitrc.yml index 5b2d35376..5abe58fe5 100644 --- a/plugins/pa11y/.toolkitrc.yml +++ b/plugins/pa11y/.toolkitrc.yml @@ -6,3 +6,5 @@ tasks: commands: 'test:local': Pa11y + +version: 2 diff --git a/plugins/package-json-hook/.toolkitrc.yml b/plugins/package-json-hook/.toolkitrc.yml index b1cc61093..2605e4902 100644 --- a/plugins/package-json-hook/.toolkitrc.yml +++ b/plugins/package-json-hook/.toolkitrc.yml @@ -1,2 +1,4 @@ installs: PackageJson: './lib/package-json-helper' + +version: 2 diff --git a/plugins/prettier/.toolkitrc.yml b/plugins/prettier/.toolkitrc.yml index 7d31a908c..79cc331f6 100644 --- a/plugins/prettier/.toolkitrc.yml +++ b/plugins/prettier/.toolkitrc.yml @@ -4,3 +4,5 @@ tasks: commands: 'format:local': Prettier 'format:staged': Prettier + +version: 2 diff --git a/plugins/serverless/.toolkitrc.yml b/plugins/serverless/.toolkitrc.yml index 9549aa534..4dc4621b9 100644 --- a/plugins/serverless/.toolkitrc.yml +++ b/plugins/serverless/.toolkitrc.yml @@ -2,3 +2,5 @@ tasks: ServerlessRun: './lib/tasks/run' ServerlessDeploy: './lib/tasks/deploy' ServerlessProvision: './lib/tasks/provision' + +version: 2 diff --git a/plugins/typescript/.toolkitrc.yml b/plugins/typescript/.toolkitrc.yml index f7b191149..20f945b9a 100644 --- a/plugins/typescript/.toolkitrc.yml +++ b/plugins/typescript/.toolkitrc.yml @@ -9,3 +9,5 @@ commands: 'build:remote': TypeScriptBuild 'run:local': TypeScriptWatch 'test:local': TypeScriptTest + +version: 2 diff --git a/plugins/upload-assets-to-s3/.toolkitrc.yml b/plugins/upload-assets-to-s3/.toolkitrc.yml index 1388260a4..a4754df00 100644 --- a/plugins/upload-assets-to-s3/.toolkitrc.yml +++ b/plugins/upload-assets-to-s3/.toolkitrc.yml @@ -3,3 +3,5 @@ tasks: commands: 'release:remote': UploadAssetsToS3 + +version: 2 diff --git a/plugins/webpack/.toolkitrc.yml b/plugins/webpack/.toolkitrc.yml index 2840e88d6..7bf7de328 100644 --- a/plugins/webpack/.toolkitrc.yml +++ b/plugins/webpack/.toolkitrc.yml @@ -8,3 +8,5 @@ commands: 'build:ci': WebpackProduction 'build:remote': WebpackProduction 'run:local': WebpackWatch + +version: 2 From 2017d0c39ba998abc1b1ff0136b02d1cc83c5d15 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 4 Apr 2024 09:52:35 +0100 Subject: [PATCH 122/321] fix: remove check for undefined commands --- core/cli/src/config.ts | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 48ae1cf3d..d0de7830d 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -12,8 +12,12 @@ import { ToolKitConflictError } from '@dotcom-tool-kit/error' import { RawConfig, ValidConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' import { formatTaskConflicts, +<<<<<<< HEAD formatUndefinedCommandTasks, formatUnusedPluginOptions, +======= + formatUnusedOptions, +>>>>>>> 6ab84a23 (fix: remove check for undefined commands) formatCommandTaskConflicts, formatHookConflicts, formatPluginOptionConflicts, @@ -94,21 +98,6 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali } } - const configuredCommandTasks = withoutConflicts(Object.values(config.commandTasks)) - const definedHookIds = new Set(Object.keys(config.hooks)) - const undefinedCommandTasks = configuredCommandTasks.filter(() => { - return false //TODO - // we only care about undefined hooks that were configured by the app, not default config from plugins - // const fromApp = commandTask.plugin.root === process.cwd() - // const hookDefined = definedHookIds.has(commandTask.id) - // return fromApp && !hookDefined - }) - - if (undefinedCommandTasks.length > 0) { - shouldThrow = true - error.details += formatUndefinedCommandTasks(undefinedCommandTasks, Array.from(definedHookIds)) - } - const invalidOptions = validatePluginOptions(logger, config) if (invalidOptions.length > 0) { @@ -139,6 +128,8 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali error.details += formatUnusedTaskOptions(unusedTaskOptions, Object.keys(config.tasks)) } + const configuredCommandTasks = withoutConflicts(Object.values(config.commandTasks)) + const missingTasks = configuredCommandTasks .map((hook) => ({ hook, From cf0684315320d4a14a0467efabbbfef305808716 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 4 Apr 2024 09:54:02 +0100 Subject: [PATCH 123/321] chore: remove unused undefined command message --- core/cli/src/config.ts | 5 ----- core/cli/src/messages.ts | 17 ----------------- 2 files changed, 22 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index d0de7830d..0f380ef20 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -12,12 +12,7 @@ import { ToolKitConflictError } from '@dotcom-tool-kit/error' import { RawConfig, ValidConfig, ValidPluginsConfig } from '@dotcom-tool-kit/config' import { formatTaskConflicts, -<<<<<<< HEAD - formatUndefinedCommandTasks, formatUnusedPluginOptions, -======= - formatUnusedOptions, ->>>>>>> 6ab84a23 (fix: remove check for undefined commands) formatCommandTaskConflicts, formatHookConflicts, formatPluginOptionConflicts, diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index fceab661e..b49d15534 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -93,23 +93,6 @@ You must resolve this conflict by providing options in your app's Tool Kit confi const formatPlugin = (plugin: Plugin): string => plugin.id === 'app root' ? s.app('your app') : `plugin ${s.plugin(plugin.id)}` -// TODO text similarity "did you mean...?" -export const formatUndefinedCommandTasks = ( - undefinedHooks: CommandTask[], - definedHooks: string[] -): string => `TODO Hooks must be defined by a plugin before you can configure a task to run for them. In your Tool Kit configuration you've configured hooks that aren't defined: - -${undefinedHooks.map((hook) => `- ${s.hook(hook.id)}`).join('\n')} - -They could be misspelt, or defined by a Tool Kit plugin that isn't installed in this app. - -${ - definedHooks.length > 0 - ? `Hooks that are defined and available for tasks are: ${definedHooks.map(s.hook).join(', ')}` - : `There are no hooks defined by this app's plugins. You probably need to install some plugins to define hooks.` -}. -` - export type InvalidOption = [string, z.ZodError] export const formatInvalidOptions = ( From cd92745a94996ecfa3baec92ac48505d83e80376 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 12 Apr 2024 09:28:40 +0100 Subject: [PATCH 124/321] chore: remove duplicate runInit call in runTasks how did that get there --- core/cli/src/tasks.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 62b687537..7fb795466 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -72,7 +72,6 @@ ${availableCommands}` await runInit(logger, config) await checkInstall(logger, config) - await runInit(logger, config) if (shouldDisableNativeFetch()) { process.execArgv.push('--no-experimental-fetch') From edb627952751c50e668e3aca044cff98f4a6b5b6 Mon Sep 17 00:00:00 2001 From: Joel Carr Date: Fri, 12 Apr 2024 09:37:32 +0100 Subject: [PATCH 125/321] chore: drop use of Node 16 and update LTS versions to latest --- .circleci/config.yml | 38 +++++++++++++++++++------------------- package-lock.json | 4 ++-- package.json | 6 +++--- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c6adc9e3c..aec6c6fb4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ references: - image: cimg/node:<< parameters.node-version >> parameters: node-version: - default: '20.10' + default: '20.12' type: string workspace_root: &workspace_root ~/project @@ -184,21 +184,21 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - test: requires: - build-v<< matrix.node-version >> name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - lint: requires: - build-v<< matrix.node-version >> name: lint-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] release-please: when: @@ -228,21 +228,21 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - test: requires: - build-v<< matrix.node-version >> name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - lint: requires: - build-v<< matrix.node-version >> name: lint-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] build-test-publish: when: @@ -257,7 +257,7 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - test: filters: <<: *filters_release_build @@ -266,7 +266,7 @@ workflows: name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - lint: filters: <<: *filters_release_build @@ -275,14 +275,14 @@ workflows: name: lint-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - publish: context: npm-publish-token filters: <<: *filters_release_build requires: - - lint-v20.10 - - test-v20.10 + - lint-v20.12 + - test-v20.12 build-test-prepublish: when: @@ -297,7 +297,7 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - test: filters: <<: *filters_prerelease_build @@ -306,7 +306,7 @@ workflows: name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - lint: filters: <<: *filters_prerelease_build @@ -315,14 +315,14 @@ workflows: name: lint-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - prepublish: context: npm-publish-token filters: <<: *filters_prerelease_build requires: - - lint-v20.10 - - test-v20.10 + - lint-v20.12 + - test-v20.12 nightly: when: @@ -339,7 +339,7 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] - test: requires: - build-v<< matrix.node-version >> @@ -347,7 +347,7 @@ workflows: name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '16.14', '18.16', '20.10' ] + node-version: [ '18.20', '20.12' ] # Prior to producing a development orb (which requires credentials) basic validation, linting, and even unit testing can be performed. # This workflow will run on every commit diff --git a/package-lock.json b/package-lock.json index d39d3c312..a2e70080a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,8 +41,8 @@ "typescript": "~4.9.5" }, "engines": { - "node": "16.x || 18.x || 20.x", - "npm": "7.x || 8.x || 9.x || 10.x" + "node": "18.x || 20.x", + "npm": "8.x || 9.x || 10.x" } }, "core/cli": { diff --git a/package.json b/package.json index e0c7938a8..4346725ad 100644 --- a/package.json +++ b/package.json @@ -58,11 +58,11 @@ "@types/superagent": "^4.1.10" }, "volta": { - "node": "20.10.0" + "node": "20.12.2" }, "engines": { - "node": "16.x || 18.x || 20.x", - "npm": "7.x || 8.x || 9.x || 10.x" + "node": "18.x || 20.x", + "npm": "8.x || 9.x || 10.x" }, "overrides": { "type-fest": "3.6.0" From 6b5d149446c07b9e9ef105ecbc3c0137a6f45ebe Mon Sep 17 00:00:00 2001 From: Joel Carr Date: Fri, 12 Apr 2024 09:39:12 +0100 Subject: [PATCH 126/321] chore!: drop support for Node 16 --- core/cli/package.json | 2 +- core/create/package.json | 2 +- lib/doppler/package.json | 2 +- lib/error/package.json | 2 +- lib/logger/package.json | 2 +- lib/options/package.json | 2 +- lib/state/package.json | 2 +- lib/vault/package.json | 2 +- lib/wait-for-ok/package.json | 2 +- plugins/babel/package.json | 2 +- plugins/backend-app/package.json | 2 +- plugins/backend-heroku-app/package.json | 2 +- plugins/backend-serverless-app/package.json | 2 +- plugins/circleci-deploy/package.json | 2 +- plugins/circleci-heroku/package.json | 2 +- plugins/circleci-npm/package.json | 2 +- plugins/circleci/package.json | 2 +- plugins/component/package.json | 2 +- plugins/cypress/package.json | 2 +- plugins/eslint/package.json | 2 +- plugins/frontend-app/package.json | 2 +- plugins/heroku/package.json | 2 +- plugins/husky-npm/package.json | 2 +- plugins/jest/package.json | 2 +- plugins/lint-staged-npm/package.json | 2 +- plugins/lint-staged/package.json | 2 +- plugins/mocha/package.json | 2 +- plugins/n-test/package.json | 2 +- plugins/next-router/package.json | 2 +- plugins/node/package.json | 2 +- plugins/nodemon/package.json | 2 +- plugins/npm/package.json | 2 +- plugins/pa11y/package.json | 2 +- plugins/package-json-hook/package.json | 2 +- plugins/prettier/package.json | 2 +- plugins/serverless/package.json | 2 +- plugins/typescript/package.json | 2 +- plugins/upload-assets-to-s3/package.json | 2 +- plugins/webpack/package.json | 2 +- 39 files changed, 39 insertions(+), 39 deletions(-) diff --git a/core/cli/package.json b/core/cli/package.json index a1404c3cb..b108b7b8c 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -60,7 +60,7 @@ "zod-validation-error": "^2.1.0" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "files": [ diff --git a/core/create/package.json b/core/create/package.json index 8b6004683..4f47a11a2 100644 --- a/core/create/package.json +++ b/core/create/package.json @@ -61,7 +61,7 @@ "extends": "../../package.json" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/lib/doppler/package.json b/lib/doppler/package.json index 9f4f7415e..6e305611b 100644 --- a/lib/doppler/package.json +++ b/lib/doppler/package.json @@ -36,7 +36,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/lib/error/package.json b/lib/error/package.json index cea6e54bd..ac75fdd09 100644 --- a/lib/error/package.json +++ b/lib/error/package.json @@ -26,7 +26,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/lib/logger/package.json b/lib/logger/package.json index d08ad1acc..ec415425f 100644 --- a/lib/logger/package.json +++ b/lib/logger/package.json @@ -35,7 +35,7 @@ "@types/triple-beam": "^1.3.2" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/lib/options/package.json b/lib/options/package.json index 5b293845f..965942d3f 100644 --- a/lib/options/package.json +++ b/lib/options/package.json @@ -25,7 +25,7 @@ ".toolkitrc.yml" ], "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/lib/state/package.json b/lib/state/package.json index 77f2a99cb..4a66fcd0c 100644 --- a/lib/state/package.json +++ b/lib/state/package.json @@ -27,7 +27,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/lib/vault/package.json b/lib/vault/package.json index 04009e9c2..a18f70cd6 100644 --- a/lib/vault/package.json +++ b/lib/vault/package.json @@ -39,7 +39,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/lib/wait-for-ok/package.json b/lib/wait-for-ok/package.json index 91d06075c..4aac74664 100644 --- a/lib/wait-for-ok/package.json +++ b/lib/wait-for-ok/package.json @@ -33,7 +33,7 @@ "extends": "../../package.json" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/babel/package.json b/plugins/babel/package.json index caeb26d50..2203478bd 100644 --- a/plugins/babel/package.json +++ b/plugins/babel/package.json @@ -40,7 +40,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/backend-app/package.json b/plugins/backend-app/package.json index 34ba99c77..34c4643f0 100644 --- a/plugins/backend-app/package.json +++ b/plugins/backend-app/package.json @@ -20,7 +20,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/backend-heroku-app/package.json b/plugins/backend-heroku-app/package.json index cb90849a0..eaf3a6410 100644 --- a/plugins/backend-heroku-app/package.json +++ b/plugins/backend-heroku-app/package.json @@ -23,7 +23,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/backend-serverless-app/package.json b/plugins/backend-serverless-app/package.json index b945f3e34..7cf3bfff5 100644 --- a/plugins/backend-serverless-app/package.json +++ b/plugins/backend-serverless-app/package.json @@ -23,7 +23,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/circleci-deploy/package.json b/plugins/circleci-deploy/package.json index a42e6f844..6a536f605 100644 --- a/plugins/circleci-deploy/package.json +++ b/plugins/circleci-deploy/package.json @@ -34,7 +34,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/circleci-heroku/package.json b/plugins/circleci-heroku/package.json index a63cb3cb3..49c0fb199 100644 --- a/plugins/circleci-heroku/package.json +++ b/plugins/circleci-heroku/package.json @@ -28,7 +28,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/circleci-npm/package.json b/plugins/circleci-npm/package.json index c7de0940c..a86f8d9c2 100644 --- a/plugins/circleci-npm/package.json +++ b/plugins/circleci-npm/package.json @@ -29,7 +29,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index f861e9dc0..1ccbbc53a 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -47,7 +47,7 @@ "zod": "^3.22.4" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/component/package.json b/plugins/component/package.json index 64b3d081b..2a1006f22 100644 --- a/plugins/component/package.json +++ b/plugins/component/package.json @@ -24,7 +24,7 @@ "@dotcom-tool-kit/npm": "^3.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/cypress/package.json b/plugins/cypress/package.json index b335be8f8..bf5491d12 100644 --- a/plugins/cypress/package.json +++ b/plugins/cypress/package.json @@ -24,7 +24,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "dependencies": { diff --git a/plugins/eslint/package.json b/plugins/eslint/package.json index 1919c9b98..9f3a7a367 100644 --- a/plugins/eslint/package.json +++ b/plugins/eslint/package.json @@ -41,7 +41,7 @@ "eslint": "7.x || 8.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/frontend-app/package.json b/plugins/frontend-app/package.json index 5908b36e9..cab619cc1 100644 --- a/plugins/frontend-app/package.json +++ b/plugins/frontend-app/package.json @@ -25,7 +25,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/heroku/package.json b/plugins/heroku/package.json index e3a44ce52..d0d8f8484 100644 --- a/plugins/heroku/package.json +++ b/plugins/heroku/package.json @@ -50,7 +50,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/husky-npm/package.json b/plugins/husky-npm/package.json index 6d7e3da27..edf6c2ac3 100644 --- a/plugins/husky-npm/package.json +++ b/plugins/husky-npm/package.json @@ -32,7 +32,7 @@ "extends": "../../package.json" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/jest/package.json b/plugins/jest/package.json index e70c10f33..fb50d453d 100644 --- a/plugins/jest/package.json +++ b/plugins/jest/package.json @@ -35,7 +35,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/lint-staged-npm/package.json b/plugins/lint-staged-npm/package.json index 72d45bdef..ac212eb65 100644 --- a/plugins/lint-staged-npm/package.json +++ b/plugins/lint-staged-npm/package.json @@ -33,7 +33,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/lint-staged/package.json b/plugins/lint-staged/package.json index d47e4365f..6a564d5ff 100644 --- a/plugins/lint-staged/package.json +++ b/plugins/lint-staged/package.json @@ -34,7 +34,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/mocha/package.json b/plugins/mocha/package.json index e5b43fce5..9f8fd5273 100644 --- a/plugins/mocha/package.json +++ b/plugins/mocha/package.json @@ -42,7 +42,7 @@ "mocha": ">=6.x <=10.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/n-test/package.json b/plugins/n-test/package.json index 76ff7552d..7ee542409 100644 --- a/plugins/n-test/package.json +++ b/plugins/n-test/package.json @@ -40,7 +40,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/next-router/package.json b/plugins/next-router/package.json index 10f89a867..a5fed136f 100644 --- a/plugins/next-router/package.json +++ b/plugins/next-router/package.json @@ -33,7 +33,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "devDependencies": { diff --git a/plugins/node/package.json b/plugins/node/package.json index 59649230c..25a66a161 100644 --- a/plugins/node/package.json +++ b/plugins/node/package.json @@ -33,7 +33,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "devDependencies": { diff --git a/plugins/nodemon/package.json b/plugins/nodemon/package.json index e29fb9c04..2fd2a9aad 100644 --- a/plugins/nodemon/package.json +++ b/plugins/nodemon/package.json @@ -37,7 +37,7 @@ "@types/nodemon": "^1.19.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/npm/package.json b/plugins/npm/package.json index de634eb59..7657658d7 100644 --- a/plugins/npm/package.json +++ b/plugins/npm/package.json @@ -46,7 +46,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/pa11y/package.json b/plugins/pa11y/package.json index 720191d2d..336c0d5cd 100644 --- a/plugins/pa11y/package.json +++ b/plugins/pa11y/package.json @@ -34,7 +34,7 @@ "@types/pa11y": "^5.3.4" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/package-json-hook/package.json b/plugins/package-json-hook/package.json index 35b110e9d..18d3b305b 100644 --- a/plugins/package-json-hook/package.json +++ b/plugins/package-json-hook/package.json @@ -42,7 +42,7 @@ "extends": "../../package.json" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/prettier/package.json b/plugins/prettier/package.json index dd50b3df1..d5e92bf73 100644 --- a/plugins/prettier/package.json +++ b/plugins/prettier/package.json @@ -44,7 +44,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/serverless/package.json b/plugins/serverless/package.json index 6ae03c4fe..0c6769543 100644 --- a/plugins/serverless/package.json +++ b/plugins/serverless/package.json @@ -35,7 +35,7 @@ "wait-port": "^0.2.9" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "devDependencies": { diff --git a/plugins/typescript/package.json b/plugins/typescript/package.json index 1a2155e42..955f8a75c 100644 --- a/plugins/typescript/package.json +++ b/plugins/typescript/package.json @@ -35,7 +35,7 @@ "winston": "^3.8.2" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/upload-assets-to-s3/package.json b/plugins/upload-assets-to-s3/package.json index a12f6f876..2357505fb 100644 --- a/plugins/upload-assets-to-s3/package.json +++ b/plugins/upload-assets-to-s3/package.json @@ -45,7 +45,7 @@ "dotcom-tool-kit": "3.x" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } diff --git a/plugins/webpack/package.json b/plugins/webpack/package.json index 7851571b3..424ecb1df 100644 --- a/plugins/webpack/package.json +++ b/plugins/webpack/package.json @@ -42,7 +42,7 @@ "extends": "../../package.json" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } } From bad89e1cf9ec9a93946ddeccf56183eb4e5dcda8 Mon Sep 17 00:00:00 2001 From: Joel Carr Date: Fri, 12 Apr 2024 09:39:54 +0100 Subject: [PATCH 127/321] build: update create script to define latest node LTS versions --- scripts/create-plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create-plugin.js b/scripts/create-plugin.js index 4f498a4e8..2252d3277 100755 --- a/scripts/create-plugin.js +++ b/scripts/create-plugin.js @@ -35,7 +35,7 @@ pkg.homepage = `https://github.com/financial-times/dotcom-tool-kit/tree/main/${d pkg.author = 'FT.com Platforms Team ' pkg.files = ['/lib', '.toolkitrc.yml'] pkg.engines = { - node: '16.x || 18.x', + node: '18.x || 20.x', npm: '7.x || 8.x || 9.x' } pkg.peerDependencies = { From 641e242f7edf95bbd7c31bcba89eb532cf9427d1 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Fri, 19 Jan 2024 19:06:37 +0000 Subject: [PATCH 128/321] feat(circleci)!: define CircleCI configs in .toolkitrc.yml Following on from similar changes to the PackageJson hook, the CircleCI hook is now configured via Tool Kit options in .toolkitrc.yml files instead of modifying shared state in JavaScript functions. This creates a declarative approach instead of the old functional approach, which should make configuration much easier to reason with and less abstract, as well as more flexible, allowing for different kinds of workflows. With this initial commit I've focused on getting the configuration generated for next-static to be functionally equivalent to what was generated previously. Subsequent work will be done to make the config generated better than what was previously generated, and to support a more diverse range of project types. --- lib/schemas/src/hooks.ts | 4 +- lib/schemas/src/hooks/circleci.ts | 38 ++ lib/schemas/src/plugins/circleci.ts | 3 +- plugins/circleci-deploy/.toolkitrc.yml | 65 +++ plugins/circleci-npm/.toolkitrc.yml | 19 + plugins/circleci/.toolkitrc.yml | 29 +- plugins/circleci/src/circleci-config.ts | 401 +++++++++------- .../circleci-config.test.ts.snap | 171 ------- plugins/circleci/test/circleci-config.test.ts | 433 +++++++++++++----- 9 files changed, 719 insertions(+), 444 deletions(-) create mode 100644 lib/schemas/src/hooks/circleci.ts delete mode 100644 plugins/circleci/test/__snapshots__/circleci-config.test.ts.snap diff --git a/lib/schemas/src/hooks.ts b/lib/schemas/src/hooks.ts index f1241a131..d53148a75 100644 --- a/lib/schemas/src/hooks.ts +++ b/lib/schemas/src/hooks.ts @@ -1,8 +1,10 @@ +import { CircleCiSchema } from './hooks/circleci' import { PackageJsonSchema } from './hooks/package-json' import { type InferSchemaOptions } from './infer' export const HookSchemas = { - PackageJson: PackageJsonSchema + PackageJson: PackageJsonSchema, + CircleCi: CircleCiSchema } export type HookOptions = InferSchemaOptions diff --git a/lib/schemas/src/hooks/circleci.ts b/lib/schemas/src/hooks/circleci.ts new file mode 100644 index 000000000..7f5cded83 --- /dev/null +++ b/lib/schemas/src/hooks/circleci.ts @@ -0,0 +1,38 @@ +import { z } from 'zod' + +export const CircleCiExecutor = z.object({ + name: z.string(), + image: z.string() +}) +export type CircleCiExecutor = z.infer +export const CircleCiJob = z.object({ + name: z.string(), + command: z.string() +}) +export type CircleCiJob = z.infer +export const CircleCiWorkflowJob = z.object({ + name: z.string(), + requires: z.array(z.string()), + splitIntoMatrix: z.boolean().optional(), + custom: z.unknown().optional() +}) +export type CircleCiWorkflowJob = z.infer +export const CircleCiWorkflow = z.object({ + name: z.string(), + jobs: z.array(CircleCiWorkflowJob), + runOnRelease: z.boolean().optional(), + custom: z.unknown().optional() +}) +export type CircleCiWorkflow = z.infer +export const CircleCiCustomConfig = z.record(z.unknown()) +export type CircleCiCustomConfig = z.infer +export const CircleCiSchema = z.object({ + executors: z.array(CircleCiExecutor).optional(), + jobs: z.array(CircleCiJob).optional(), + workflows: z.array(CircleCiWorkflow).optional(), + custom: CircleCiCustomConfig.optional() +}) + +export type CircleCiOptions = z.infer + +export const Schema = CircleCiSchema diff --git a/lib/schemas/src/plugins/circleci.ts b/lib/schemas/src/plugins/circleci.ts index a655d13cc..f5695a87f 100644 --- a/lib/schemas/src/plugins/circleci.ts +++ b/lib/schemas/src/plugins/circleci.ts @@ -1,8 +1,7 @@ import { z } from 'zod' export const CircleCISchema = z.object({ - nodeVersion: z.string().or(z.string().array()).default('18.18-browsers'), - cypressImage: z.string().optional() + cimgNodeVersions: z.string().array().default(['18.19-browsers']) }) export type CircleCIOptions = z.infer diff --git a/plugins/circleci-deploy/.toolkitrc.yml b/plugins/circleci-deploy/.toolkitrc.yml index 7a8faa61f..f7eebc84e 100644 --- a/plugins/circleci-deploy/.toolkitrc.yml +++ b/plugins/circleci-deploy/.toolkitrc.yml @@ -1,4 +1,69 @@ plugins: - '@dotcom-tool-kit/circleci' +options: + hooks: + - CircleCi: + jobs: + - name: deploy-review + command: 'deploy:review' + - name: deploy-staging + command: 'deploy:staging' + - name: e2e-test-review + command: 'test:review' + - name: e2e-test-staging + command: 'test:staging' + - name: deploy-production + command: 'deploy:production' + workflows: + - name: 'tool-kit' + jobs: + - name: 'deploy-review' + requires: + - 'setup' + - 'waiting-for-approval' + splitIntoMatrix: false + custom: + filters: + branches: + ignore: main + - name: 'deploy-staging' + requires: + - 'setup' + splitIntoMatrix: false + custom: + filters: + branches: + only: main + - name: 'e2e-test-review' + requires: + - 'deploy-review' + splitIntoMatrix: false + custom: + - name: 'e2e-test-staging' + splitIntoMatrix: false + requires: + - 'deploy-staging' + custom: + - name: 'deploy-production' + requires: + - 'test' + - 'e2e-test-staging' + splitIntoMatrix: false + custom: + filters: + branches: + only: main + - name: 'nightly' + jobs: + - name: 'deploy-review' + requires: + - 'setup' + - 'waiting-for-approval' + splitIntoMatrix: false + custom: + filters: + branches: + ignore: main + version: 2 diff --git a/plugins/circleci-npm/.toolkitrc.yml b/plugins/circleci-npm/.toolkitrc.yml index fd7b8e187..4e3d3d009 100644 --- a/plugins/circleci-npm/.toolkitrc.yml +++ b/plugins/circleci-npm/.toolkitrc.yml @@ -5,4 +5,23 @@ plugins: commands: 'publish:tag': NpmPublish +options: + hooks: + - CircleCi: + jobs: + - name: publish-tag + command: 'publish:tag' + workflows: + - name: 'tool-kit' + jobs: + - name: 'publish-tag' + requires: + - 'test' + splitIntoMatrix: true + custom: + context: 'npm-publish-token' + filters: + branches: + ignore: '/.*/' + version: 2 diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index 9bc57a6dc..b96153b90 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -1,5 +1,32 @@ installs: - CircleCiConfig: './lib/circleci-config' + CircleCi: './lib/circleci-config' + +options: + hooks: + - CircleCi: + jobs: + - name: build + command: 'build:ci' + - name: test + command: 'test:ci' + workflows: + - name: 'tool-kit' + jobs: + - name: build + requires: + - 'setup' + - name: test + requires: + - 'build' + runOnRelease: true + - name: 'nightly' + jobs: + - name: build + requires: + - 'setup' + - name: test + requires: + - 'build' init: - './lib/init-env-vars' diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index baf18dc1a..e4b918878 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -1,18 +1,25 @@ +import type { + CircleCiOptions, + CircleCiSchema, + CircleCiWorkflow +} from '@dotcom-tool-kit/schemas/lib/hooks/circleci' +import { type Conflict, isConflict } from '@dotcom-tool-kit/conflict' +import { Hook, type HookInstallation } from '@dotcom-tool-kit/base' +import { type Plugin } from '@dotcom-tool-kit/plugin' import { ToolKitError } from '@dotcom-tool-kit/error' import { styles } from '@dotcom-tool-kit/logger' import { getOptions } from '@dotcom-tool-kit/options' -import { Hook } from '@dotcom-tool-kit/base' import { promises as fs } from 'fs' import { diffStringsUnified } from 'jest-diff' +import groupBy from 'lodash/groupBy' import isPlainObject from 'lodash/isPlainObject' import isMatch from 'lodash/isMatch' import merge from 'lodash/merge' import mergeWith from 'lodash/mergeWith' -import omit from 'lodash/omit' import path from 'path' +import partition from 'lodash/partition' import type { PartialDeep } from 'type-fest' import YAML from 'yaml' -import type { z } from 'zod' const automatedComment = '# CONFIG GENERATED BY DOTCOM-TOOL-KIT, DO NOT EDIT BY HAND\n' @@ -26,19 +33,12 @@ type JobConfig = { [parameter: string]: unknown } -type TriggerConfig = { - schedule?: { cron: string; filters?: { branches: { only?: string; ignore?: string } } } -} +type Step = Record type Job = string | { [job: string]: JobConfig } -type Trigger = string | { [trigger: string]: TriggerConfig } - -type Workflow = { - jobs?: Job[] - triggers?: Trigger[] -} - +// TODO:20240410:IM rethink this whole type, it's very fly-by-night at the +// moment and constantly requires updates whenever we change the code interface CircleConfig { version: 2.1 orbs: { @@ -51,30 +51,15 @@ interface CircleConfig { } jobs: { [job: string]: { - docker: { image: string }[] - steps: (string | { [command: string]: { path?: string } })[] + docker?: { image: string }[] + executor?: string + parameters?: unknown + steps: (string | { [command: string]: Step })[] } } workflows: { - 'tool-kit': { - when: { - not: { - equal: ['scheduled_pipeline', '<< pipeline.trigger_source >>'] - } - } - jobs: Job[] - } - nightly: { - when: { - and: [ - { - equal: ['scheduled_pipeline', '<< pipeline.trigger_source >>'] - }, - { - equal: ['nightly', '<< pipeline.schedule.name >>'] - } - ] - } + [workflow: string]: { + when: unknown jobs: Job[] } } @@ -99,8 +84,7 @@ const getNodeVersions = (): Array => { // empty string. The first executor is named 'node' without any reference to // the version so the plugins which don't support matrices don't need to know // the version option. - const nodeVersion = getOptions('@dotcom-tool-kit/circleci')?.nodeVersion ?? '' - return Array.isArray(nodeVersion) ? nodeVersion : [nodeVersion] + return getOptions('@dotcom-tool-kit/circleci')?.cimgNodeVersions ?? [''] } /* Applies a verion identifier for all but the first (and therefore default) @@ -113,19 +97,9 @@ const nodeVersionToExecutor = (version: string, index: number): string => // spread into your custom config, and are automatically included when calling // generateSimpleJob. -/** - * Every Tool Kit job uses a Node executor. We define a list of possible Node - * executors at the top of the CircleCI config, and jobs can either opt for the - * default executor (shortened to just 'node') with `nightlyBoilerplate` or to - * run with all the different executors in a matrix via `matrixBoilerplate`. - * version of Node to use. - */ -export const nightlyBoilerplate = { - executor: 'node' -} // Needs to be lazy as the node versions haven't been loaded yet when this // module is initialised. -export const matrixBoilerplate = () => ({ +const matrixBoilerplate = () => ({ matrix: { parameters: { executor: getNodeVersions().map(nodeVersionToExecutor) @@ -138,82 +112,15 @@ export const matrixBoilerplate = () => ({ * when doing a release if the filter isn't made explicit */ export const tagFilter = { filters: { tags: { only: `${/^v\d+\.\d+\.\d+(-.+)?/}` } } } -/** - * @deprecated explicitly using each of the objects this spreads is preferred. - * jobBoilerplate is the config needed for all Tool Kit jobs in the `tool-kit` - * workflow, and combines the `nightlyBoilerplate` and `tagFilter` objects. - */ -export const jobBoilerplate = { - ...nightlyBoilerplate, - ...tagFilter -} -export interface JobGeneratorOptions { - name: string - /** whether to include in `nightly` workflow or just `tool-kit` */ - addToNightly: boolean - requires: string[] - /** whether this job can be run multiple times with different Node versions */ - splitIntoMatrix: boolean - /** other fields to include in the job */ - additionalFields?: JobConfig -} - -/** - * `generateConfigWithJob` generates a single job, structured so that it will - * merge nicely with the rest of the config. This will include the `requires` - * parameter, as well as the boilerplate properties from `matrixBoilerplate`, - * but any other options will need to be passed to `additionalFields`, such as - * `filters.branches`. - */ -export const generateConfigWithJob = (options: JobGeneratorOptions): CircleCIStatePartial => { - const jobBase = options.splitIntoMatrix - ? { - name: `${options.name}-<< matrix.executor >>`, - requires: options.requires.map((dep) => - dep === 'waiting-for-approval' ? dep : `${dep}-<< matrix.executor >>` - ), - ...matrixBoilerplate() - } - : { - // only require the latest Node version of a matrix job in order to - // avoid workspace conflicts - requires: options.requires.map((dep) => (dep === 'waiting-for-approval' ? dep : `${dep}-node`)), - // append the default executor name to the job name so that multiple - // non-matrix jobs can be chained one after another without having to - // know whether a matrix job precedes them or not - name: `${options.name}-node`, - ...nightlyBoilerplate - } - const config: CircleCIStatePartial = { - workflows: { - 'tool-kit': { - jobs: [ - { - // avoid overwriting the jobBase variable - [options.name]: merge({}, jobBase, tagFilter, options.additionalFields) - } - ] - } - } - } - if (options.addToNightly) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - config.workflows!.nightly = { - jobs: [ - { - [options.name]: merge( - { ...jobBase, requires: jobBase.requires.filter((dep) => dep !== 'waiting-for-approval') }, - omit(options.additionalFields, ['filters']) - ) - } - ] +const mergeWithConcatenatedArrays = (arg0: unknown, ...args: unknown[]) => + mergeWith(arg0, ...args, (obj: unknown, source: unknown) => { + if (Array.isArray(obj)) { + return obj.concat(source) } - } - return config -} + }) -const getInitialState = (): CircleCIState => { +const getBaseConfig = (): CircleCIState => { return { version: 2.1, orbs: { @@ -293,33 +200,155 @@ const getInitialState = (): CircleCIState => { } } +const rootOptionKeys = ['executors', 'jobs', 'workflows'] as const satisfies readonly (keyof Omit< + CircleCiOptions, + 'custom' +>)[] + const isAutomatedConfig = (config: string): boolean => config.startsWith(automatedComment) const isNotToolKitConfig = (config: string): boolean => !config.includes('tool-kit') -const getJobName = (job: Job): string => (typeof job === 'string' ? job : Object.keys(job)[0]) +const isObject = (val: unknown): val is Record => isPlainObject(val) + +const customOptionsOverlap = ( + installation: Record, + other: Record +): boolean => + Object.entries(installation).some(([key, value]) => { + if (key in other) { + const otherVal = other[key] + if (isObject(value) && isObject(otherVal)) { + return customOptionsOverlap(value, otherVal) + } else if (Array.isArray(value) && Array.isArray(otherVal)) { + return false + } else { + return value !== otherVal + } + } else { + return false + } + }) + +const rootOptionOverlaps = (root: { name: string }[], other: { name: string }[]): boolean => { + const otherNames = other.map(({ name }) => name) + return root.map(({ name }) => name).some((name) => otherNames.includes(name)) +} + +const installationsOverlap = ( + installation: HookInstallation, + other: HookInstallation +): boolean => + customOptionsOverlap(installation.options?.custom ?? {}, other.options?.custom ?? {}) || + rootOptionKeys.some((rootOption) => + rootOptionOverlaps(installation.options?.[rootOption] ?? [], other.options?.[rootOption] ?? []) + ) -const hasJob = (expectedJob: string, jobs: NonNullable): boolean => - jobs.some( - (job) => - (typeof job === 'string' && job === expectedJob) || - (typeof job === 'object' && job.hasOwnProperty(expectedJob)) +const partitionInstallations = ( + installation: HookInstallation, + mergeable: HookInstallation[], + unmergeable: HookInstallation[] +): [HookInstallation[], HookInstallation[]] => { + const [noLongerMergeable, stillMergeable] = partition(mergeable, (other) => + installationsOverlap(installation, other) ) -export default abstract class CircleCiConfig extends Hook { - installGroup = 'circleci' + const overlapsWithUnmergeable = unmergeable.some((other) => installationsOverlap(installation, other)) + + if (noLongerMergeable.length > 0 || overlapsWithUnmergeable) { + return [stillMergeable, [...unmergeable, ...noLongerMergeable, installation]] + } + return [[...stillMergeable, installation], unmergeable] +} + +const mergeRootOptions = (options: T[]): T[] => + Object.values(groupBy(options, 'name')).map((matching) => mergeWithConcatenatedArrays({}, ...matching)) + +const mergeInstallationResults = ( + plugin: Plugin, + mergeable: HookInstallation[], + unmergeable: HookInstallation[] +) => { + const results: (HookInstallation | Conflict)[] = [] + + if (mergeable.length > 0) { + results.push({ + plugin, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + ...Object.fromEntries( + rootOptionKeys.map((rootKey) => { + const rootOptions = mergeable.flatMap<{ name: string }>( + (installation) => installation.options[rootKey] ?? [] + ) + return [rootKey, mergeRootOptions(rootOptions)] + }) + ), + custom: mergeWithConcatenatedArrays( + {}, + ...mergeable.map((installation) => installation.options.custom) + ) + } + }) + } + + if (unmergeable.length > 0) { + results.push({ + plugin, + conflicting: unmergeable + }) + } + + return results +} + +const toolKitOrbPrefix = (job: string) => `tool-kit/${job}` + +const generateJobs = (workflow: CircleCiWorkflow): Job[] => + workflow.jobs.map((job) => { + const splitIntoMatrix = job.splitIntoMatrix ?? true + return { + [toolKitOrbPrefix(job.name)]: merge( + splitIntoMatrix ? { name: `tool-kit/${job.name}-<< matrix.executor >>` } : {}, + { + requires: job.requires.map((required) => { + if (['checkout', 'waiting-for-approval'].includes(required)) { + return required + } + const requiredOrb = toolKitOrbPrefix(required) + const splitRequiredIntoMatrix = + workflow.jobs?.find(({ name: jobName }) => required === jobName)?.splitIntoMatrix ?? true + if (!splitRequiredIntoMatrix) { + return requiredOrb + } + return `${requiredOrb}-${splitIntoMatrix ? '<< matrix.executor >>' : 'node'}` + }) + }, + splitIntoMatrix + ? { + matrix: { parameters: { executor: getNodeVersions().map(nodeVersionToExecutor) } } + } + : { + executor: 'node' + }, + workflow.runOnRelease ? tagFilter : {}, + job.custom + ) + } + }) + +export default class CircleCi extends Hook { circleConfigPath = path.resolve(process.cwd(), '.circleci/config.yml') - _circleConfig?: string - haveCheckedBaseConfig = false - _versionTag?: string - abstract config: CircleCIStatePartial + private circleConfig?: string + private generatedConfig?: CircleCIState async getCircleConfig(): Promise { - if (!this._circleConfig) { + if (!this.circleConfig) { try { this.logger.verbose(`trying to read CircleCI config at ${styles.filepath(this.circleConfigPath)}...`) - this._circleConfig = await fs.readFile(this.circleConfigPath, 'utf8') + this.circleConfig = await fs.readFile(this.circleConfigPath, 'utf8') } catch (err) { // Not an error if config file doesn't exist if ((err as NodeJS.ErrnoException).code !== 'ENOENT') { @@ -328,7 +357,84 @@ export default abstract class CircleCiConfig extends Hook | Conflict>)[] + ): (HookInstallation | Conflict)[] { + const [mergeable, unmergeable] = childInstallations.reduce< + [HookInstallation[], HookInstallation[]] + >( + ([mergeable, unmergeable], installation) => { + if (isConflict(installation)) { + return [mergeable, [...unmergeable, ...installation.conflicting]] + } else { + return partitionInstallations(installation, mergeable, unmergeable) + } + }, + [[], []] + ) + + return mergeInstallationResults(plugin, mergeable, unmergeable) + } + + static overrideChildInstallations( + plugin: Plugin, + parentInstallation: HookInstallation, + childInstallations: (HookInstallation | Conflict>)[] + ): (HookInstallation | Conflict>)[] { + const mergeable: HookInstallation[] = [] + const unmergeable: HookInstallation[] = [] + + for (const installation of childInstallations) { + // TODO:IM there are multiple kinds of conflicts and this code currently + // assumes a parent resolving one conflict resolves them all + if (isConflict(installation)) { + const [canHandle, cannotHandle] = partition(installation.conflicting, (other) => + installationsOverlap(parentInstallation, other) + ) + + mergeable.push(...canHandle) + unmergeable.push(...cannotHandle) + } else { + mergeable.push(installation) + } + } + + mergeable.push(parentInstallation) + + return mergeInstallationResults(plugin, mergeable, unmergeable) + } + + generateConfig(): CircleCIState { + if (!this.generatedConfig) { + const generated = { + executors: Object.fromEntries( + this.options.executors?.map( + (executor) => [executor.name, { docker: [{ image: executor.image }] }], + {} + ) ?? [] + ), + workflows: Object.fromEntries( + this.options.workflows?.map((workflow) => { + const generatedJobs = { + jobs: generateJobs(workflow) + } + return [workflow.name, mergeWithConcatenatedArrays(generatedJobs, workflow.custom)] + }) ?? [] + ) + } satisfies CircleCIStatePartial + this.generatedConfig = mergeWithConcatenatedArrays( + {}, + getBaseConfig(), + generated, + this.options.custom ?? {} + ) + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return this.generatedConfig! } async isInstalled(): Promise { @@ -338,29 +444,12 @@ export default abstract class CircleCiConfig extends Hook { - if (!state) { - state = getInitialState() - } - // define a customiser function to make sure only jobs that aren't already - // listed are merged into the CircleCI config, and to force new jobs to be - // concatenated onto the array of other jobs rather than zipping them - // (i.e., overwriting the first few jobs in the array) - mergeWith(state, this.config, (prevState, newConfig, key) => { - if (key === 'jobs' && Array.isArray(prevState)) { - const uniqueJobs = newConfig.filter((job: Job) => !hasJob(getJobName(job), prevState)) - return prevState.concat(uniqueJobs) - } - }) - return state + async install(): Promise { + return this.generateConfig() } async commitInstall(state: CircleCIState): Promise { diff --git a/plugins/circleci/test/__snapshots__/circleci-config.test.ts.snap b/plugins/circleci/test/__snapshots__/circleci-config.test.ts.snap deleted file mode 100644 index 536edd37e..000000000 --- a/plugins/circleci/test/__snapshots__/circleci-config.test.ts.snap +++ /dev/null @@ -1,171 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CircleCI config hook install correctly generates a new configuration file 1`] = ` -Object { - "executors": Object { - "node": Object { - "docker": Array [ - Object { - "image": "cimg/node:16.14-browsers", - }, - ], - }, - }, - "jobs": Object { - "checkout": Object { - "docker": Array [ - Object { - "image": "cimg/base:stable", - }, - ], - "steps": Array [ - "checkout", - Object { - "tool-kit/persist-workspace": Object { - "path": ".", - }, - }, - ], - }, - }, - "orbs": Object { - "tool-kit": "financial-times/dotcom-tool-kit@5", - }, - "version": 2.1, - "workflows": Object { - "nightly": Object { - "jobs": Array [ - "checkout", - Object { - "tool-kit/setup": Object { - "matrix": Object { - "parameters": Object { - "executor": Array [ - "node", - ], - }, - }, - "name": "tool-kit/setup-<< matrix.executor >>", - "requires": Array [ - "checkout", - ], - }, - }, - Object { - "test-job": Object { - "executor": "node", - "name": "test-job-node", - "requires": Array [ - "that-job-node", - ], - }, - }, - ], - "when": Object { - "and": Array [ - Object { - "equal": Array [ - "scheduled_pipeline", - "<< pipeline.trigger_source >>", - ], - }, - Object { - "equal": Array [ - "nightly", - "<< pipeline.schedule.name >>", - ], - }, - ], - }, - }, - "tool-kit": Object { - "jobs": Array [ - Object { - "checkout": Object { - "filters": Object { - "tags": Object { - "only": "/^v\\\\d+\\\\.\\\\d+\\\\.\\\\d+(-.+)?/", - }, - }, - }, - }, - Object { - "waiting-for-approval": Object { - "filters": Object { - "branches": Object { - "only": "/(^renovate-.*|^nori/.*)/", - }, - }, - "type": "approval", - }, - }, - Object { - "tool-kit/setup": Object { - "filters": Object { - "tags": Object { - "only": "/^v\\\\d+\\\\.\\\\d+\\\\.\\\\d+(-.+)?/", - }, - }, - "matrix": Object { - "parameters": Object { - "executor": Array [ - "node", - ], - }, - }, - "name": "tool-kit/setup-<< matrix.executor >>", - "requires": Array [ - "checkout", - "waiting-for-approval", - ], - }, - }, - Object { - "test-job": Object { - "executor": "node", - "filters": Object { - "tags": Object { - "only": "/^v\\\\d+\\\\.\\\\d+\\\\.\\\\d+(-.+)?/", - }, - }, - "name": "test-job-node", - "requires": Array [ - "waiting-for-approval", - "that-job-node", - ], - }, - }, - Object { - "test-another-job": Object { - "filters": Object { - "tags": Object { - "only": "/^v\\\\d+\\\\.\\\\d+\\\\.\\\\d+(-.+)?/", - }, - }, - "matrix": Object { - "parameters": Object { - "executor": Array [ - "node", - ], - }, - }, - "name": "test-another-job-<< matrix.executor >>", - "requires": Array [ - "waiting-for-approval", - "this-job-<< matrix.executor >>", - ], - }, - }, - ], - "when": Object { - "not": Object { - "equal": Array [ - "scheduled_pipeline", - "<< pipeline.trigger_source >>", - ], - }, - }, - }, - }, -} -`; diff --git a/plugins/circleci/test/circleci-config.test.ts b/plugins/circleci/test/circleci-config.test.ts index a2a447c86..f70765430 100644 --- a/plugins/circleci/test/circleci-config.test.ts +++ b/plugins/circleci/test/circleci-config.test.ts @@ -1,12 +1,19 @@ -import { setOptions } from '@dotcom-tool-kit/options/lib' +import { type HookInstallation } from '@dotcom-tool-kit/base' +import { setOptions } from '@dotcom-tool-kit/options' +import type { + CircleCiWorkflowJob, + CircleCiJob, + CircleCiOptions +} from '@dotcom-tool-kit/schemas/lib/hooks/circleci' import { describe, expect, it } from '@jest/globals' import fs from 'fs' import path from 'path' import winston, { Logger } from 'winston' import * as YAML from 'yaml' -import CircleCiConfigHook, { generateConfigWithJob } from '../src/circleci-config' -const logger = (winston as unknown) as Logger +import CircleCi from '../src/circleci-config' + +const logger = winston as unknown as Logger jest.mock('fs', () => { const originalModule = jest.requireActual('fs') @@ -18,59 +25,58 @@ jest.mock('fs', () => { }) const mockedWriteFile = jest.mocked(fs.promises.writeFile) -describe('CircleCI config hook', () => { - abstract class FakeCircleCiConfigHook extends CircleCiConfigHook { - // pretend it's never the first time we've opened the config so that we - // skip the comparison with the base config generated by getInitialState() - haveCheckedBaseConfig = true - } - class TestHook extends FakeCircleCiConfigHook { - config = generateConfigWithJob({ - name: 'test-job', - addToNightly: true, - requires: ['waiting-for-approval', 'that-job'], - splitIntoMatrix: false - }) - } - class TestAnotherHook extends FakeCircleCiConfigHook { - config = generateConfigWithJob({ - name: 'test-another-job', - addToNightly: false, - requires: ['waiting-for-approval', 'this-job'], - splitIntoMatrix: true - }) - } +const testJob: CircleCiJob = { + name: 'test-job', + command: 'test:local' +} +const testWorkflowJob: CircleCiWorkflowJob = { + name: 'test-job', + requires: ['waiting-for-approval', 'that-job'], + splitIntoMatrix: false +} +const overriddenTestJob: CircleCiJob = { ...testJob, command: 'test:override' } +const anotherTestJob: CircleCiJob = { + name: 'another-test-job', + command: 'test:ci' +} +const anotherTestWorkflowJob: CircleCiWorkflowJob = { + name: 'another-test-job', + requires: ['waiting-for-approval', 'this-job'], + splitIntoMatrix: true +} +const simpleOptions: CircleCiOptions = { + jobs: [testJob], + workflows: [{ name: 'tool-kit', jobs: [testWorkflowJob] }] +} +describe('CircleCI config hook', () => { const originalDir = process.cwd() beforeAll(() => { // mirror the default options created by zod - setOptions('@dotcom-tool-kit/circleci', { nodeVersion: '16.14-browsers' }) + setOptions('@dotcom-tool-kit/circleci', { cimgNodeVersions: ['16.14-browsers'] }) }) afterEach(() => { process.chdir(originalDir) }) - describe('check', () => { + describe.skip('check', () => { it('should return true if the hook job is in the circleci workflow', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) - const hook = new TestHook(logger, 'TestHook') + const hook = new CircleCi(logger, 'CircleCi', {}) expect(await hook.isInstalled()).toBeTruthy() }) it('should return false if the hook job is not in the circleci workflow', async () => { process.chdir(path.join(__dirname, 'files', 'without-hook')) - const hook = new TestHook(logger, 'TestHook') + const hook = new CircleCi(logger, 'CircleCi', simpleOptions) expect(await hook.isInstalled()).toBeFalsy() }) it('should return false if the base configuration is missing', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) - const hook = new TestHook(logger, 'TestHook') - // reset field overridden by FakeCircleCiConfigHook so that we do check - // for the base config - hook.haveCheckedBaseConfig = false + const hook = new CircleCi(logger, 'CircleCi', simpleOptions) expect(await hook.isInstalled()).toBeFalsy() }) }) @@ -78,7 +84,7 @@ describe('CircleCI config hook', () => { describe('install', () => { it("should throw an error explaining how to autogenerate config if existing config file doesn't contain any tool-kit jobs", async () => { process.chdir(path.join(__dirname, 'files', 'without-tool-kit')) - const hook = new TestHook(logger, 'TestHook') + const hook = new CircleCi(logger, 'CircleCi', simpleOptions) const state = await hook.install() await expect(hook.commitInstall(state)).rejects.toThrow( "Your project has an existing CircleCI config file which doesn't contain" @@ -87,7 +93,7 @@ describe('CircleCI config hook', () => { it('should throw an error explaining what to do if no autogenerated comment', async () => { process.chdir(path.join(__dirname, 'files', 'without-hook')) - const hook = new TestHook(logger, 'TestHook') + const hook = new CircleCi(logger, 'CircleCi', simpleOptions) const state = await hook.install() await expect(hook.commitInstall(state)).rejects.toThrow( 'Your CircleCI configuration is missing the expected fields from Tool Kit:' @@ -97,112 +103,313 @@ describe('CircleCI config hook', () => { it("should add a job with its jobConfig to a file with a comment if it's not there", async () => { process.chdir(path.join(__dirname, 'files', 'comment-without-hook')) - const hook = new TestHook(logger, 'TestHook') + const hook = new CircleCi(logger, 'CircleCi', simpleOptions) const state = await hook.install() await hook.commitInstall(state) const config = YAML.parse(mockedWriteFile.mock.calls[0][1] as string) expect(config).toEqual( expect.objectContaining({ - workflows: { + workflows: expect.objectContaining({ 'tool-kit': expect.objectContaining({ jobs: expect.arrayContaining([ expect.objectContaining({ - 'test-job': expect.objectContaining({ - requires: ['waiting-for-approval', 'that-job-node'] + 'tool-kit/test-job': expect.objectContaining({ + requires: ['waiting-for-approval', 'tool-kit/that-job-node'] }) }) ]) - }), - nightly: expect.objectContaining({ - jobs: expect.arrayContaining([ - { - 'test-job': expect.objectContaining({ - requires: ['that-job-node'] - }) - } - ]) }) - } + }) }) ) }) + }) - it('should merge jobs from two hooks', async () => { - process.chdir(path.join(__dirname, 'files', 'comment-without-hook')) + describe('conflict resolution', () => { + it('should merge children setting different fields', () => { + const childInstallations: HookInstallation[] = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + executors: [ + { + name: 'test-executor', + image: 'cimg/node:16.19' + } + ] + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + jobs: [testJob] + } + }, + { + plugin: { id: 'c', root: 'plugins/c' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + workflows: [{ name: 'test-workflow', jobs: [testWorkflowJob], runOnRelease: true }] + } + } + ] + const plugin = { id: 'p', root: 'plugins/p' } - const hook = new TestHook(logger, 'TestHook') - const anotherHook = new TestAnotherHook(logger, 'TestAnotherHook') - let state = await hook.install() - state = await anotherHook.install(state) - await hook.commitInstall(state) + expect(CircleCi.mergeChildInstallations(plugin, childInstallations)).toEqual([ + { + plugin, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: expect.objectContaining({ + executors: [ + { + name: 'test-executor', + image: 'cimg/node:16.19' + } + ], + jobs: [testJob], + workflows: [{ name: 'test-workflow', jobs: [testWorkflowJob], runOnRelease: true }] + }) + } + ]) + }) - const config = YAML.parse(mockedWriteFile.mock.calls[0][1] as string) - expect(config).toEqual( - expect.objectContaining({ - workflows: { - 'tool-kit': expect.objectContaining({ - jobs: expect.arrayContaining([ - expect.objectContaining({ - 'test-job': expect.objectContaining({ - requires: ['waiting-for-approval', 'that-job-node'] - }) - }), - expect.objectContaining({ - 'test-another-job': expect.objectContaining({ - requires: ['waiting-for-approval', 'this-job-<< matrix.executor >>'] - }) - }) - ]) - }), - nightly: expect.objectContaining({ - jobs: expect.arrayContaining([ - { - 'test-job': expect.objectContaining({ - requires: ['that-job-node'] - }) - } - ]) - }) + it('should merge child overriding root options', () => { + const plugin = { id: 'p', root: 'plugins/p' } + const parentInstallation: HookInstallation = { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + jobs: [overriddenTestJob], + workflows: [{ name: 'test-workflow', jobs: [anotherTestWorkflowJob] }] + } + } + + const childInstallations: HookInstallation[] = [ + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + jobs: [testJob], + workflows: [{ name: 'test-workflow', jobs: [testWorkflowJob], runOnRelease: true }] } - }) - ) + } + ] + + expect(CircleCi.overrideChildInstallations(plugin, parentInstallation, childInstallations)).toEqual([ + { + plugin, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: expect.objectContaining({ + jobs: [overriddenTestJob], + workflows: [ + { name: 'test-workflow', jobs: [testWorkflowJob, anotherTestWorkflowJob], runOnRelease: true } + ] + }) + } + ]) }) - it('should discard job from duplicate hook', async () => { - process.chdir(path.join(__dirname, 'files', 'comment-without-hook')) + it('should merge sibling plugins setting the same field', () => { + const childInstallations: HookInstallation[] = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + jobs: [testJob] + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + jobs: [anotherTestJob] + } + } + ] - const hook = new TestHook(logger, 'TestHook') - const sameHook = new TestHook(logger, 'TestHook') - let state = await hook.install() - state = await sameHook.install(state) - await hook.commitInstall(state) + const plugin = { id: 'p', root: 'plugins/p' } - const config = YAML.parse(mockedWriteFile.mock.calls[0][1] as string) - const partialExpectedJob = { - 'test-job': expect.objectContaining({ - requires: ['waiting-for-approval', 'that-job-node'] - }) - } - const { jobs } = config.workflows['tool-kit'] - expect(jobs).toHaveLength(4) - for (let i = 0; i < 3; i++) { - expect(jobs[i]).toEqual(expect.not.objectContaining(partialExpectedJob)) - } - expect(jobs[3]).toEqual(expect.objectContaining(partialExpectedJob)) + expect(CircleCi.mergeChildInstallations(plugin, childInstallations)).toEqual([ + { + plugin, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: expect.objectContaining({ + jobs: expect.arrayContaining([testJob, anotherTestJob]) + }) + } + ]) }) - it('correctly generates a new configuration file', async () => { - process.chdir(path.join(__dirname, 'files', 'comment-without-hook')) + it('should conflict sibling plugins setting the same job', () => { + const childInstallations: HookInstallation[] = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + jobs: [testJob] + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + jobs: [overriddenTestJob] + } + } + ] - const hook = new TestHook(logger, 'TestHook') - const anotherHook = new TestAnotherHook(logger, 'TestAnotherHook') - let state = await hook.install() - state = await anotherHook.install(state) - await hook.commitInstall(state) + const plugin = { id: 'p', root: 'plugins/p' } - const config = YAML.parse(mockedWriteFile.mock.calls[0][1] as string) - expect(config).toMatchSnapshot() + expect(CircleCi.mergeChildInstallations(plugin, childInstallations)).toEqual([ + { + plugin, + conflicting: childInstallations + } + ]) + }) + + it('should conflict sibling plugins with the same custom field', () => { + const childInstallations: HookInstallation[] = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + custom: { + version: '2.0' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + custom: { + version: '2.1' + } + } + } + ] + + const plugin = { id: 'p', root: 'plugins/p' } + + expect(CircleCi.mergeChildInstallations(plugin, childInstallations)).toEqual([ + { + plugin, + conflicting: childInstallations + } + ]) + }) + + it('should conflict sibling plugins with the same deep custom field', () => { + const childInstallations: HookInstallation[] = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + custom: { + parameters: { + 'test-param': { + type: 'string', + default: 'test' + } + } + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + custom: { + parameters: { + 'test-param': { + type: 'number', + default: 137 + } + } + } + } + } + ] + + const plugin = { id: 'p', root: 'plugins/p' } + + expect(CircleCi.mergeChildInstallations(plugin, childInstallations)).toEqual([ + { + plugin, + conflicting: childInstallations + } + ]) + }) + + it('should merge sibling plugins with different custom fields', () => { + const childInstallations: HookInstallation[] = [ + { + plugin: { id: 'a', root: 'plugins/a' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + custom: { + version: '2.0' + } + } + }, + { + plugin: { id: 'b', root: 'plugins/b' }, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: { + custom: { + parameters: { + 'test-param': { + type: 'number', + default: 137 + } + } + } + } + } + ] + + const plugin = { id: 'p', root: 'plugins/p' } + + expect(CircleCi.mergeChildInstallations(plugin, childInstallations)).toEqual([ + { + plugin, + forHook: 'CircleCi', + hookConstructor: CircleCi, + options: expect.objectContaining({ + custom: { + version: '2.0', + parameters: { + 'test-param': { + type: 'number', + default: 137 + } + } + } + }) + } + ]) }) }) }) From 37507f1cad182fcc6956067017cb5ab056ea78b9 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Fri, 12 Apr 2024 15:27:12 +0100 Subject: [PATCH 129/321] feat(circleci): allow projects to rewrite whole CircleCI config This will be useful if, for example, a project doesn't want the tool-kit workflow, or the Tool Kit orb. It also allows our tests to be simpler as we only have to account for the options we've explicitly specified. --- lib/schemas/src/hooks/circleci.ts | 3 ++- plugins/circleci/src/circleci-config.ts | 24 +++++++++---------- plugins/circleci/test/circleci-config.test.ts | 9 +++---- .../test/files/with-hook/.circleci/config.yml | 16 ++----------- 4 files changed, 21 insertions(+), 31 deletions(-) diff --git a/lib/schemas/src/hooks/circleci.ts b/lib/schemas/src/hooks/circleci.ts index 7f5cded83..68d92de4c 100644 --- a/lib/schemas/src/hooks/circleci.ts +++ b/lib/schemas/src/hooks/circleci.ts @@ -30,7 +30,8 @@ export const CircleCiSchema = z.object({ executors: z.array(CircleCiExecutor).optional(), jobs: z.array(CircleCiJob).optional(), workflows: z.array(CircleCiWorkflow).optional(), - custom: CircleCiCustomConfig.optional() + custom: CircleCiCustomConfig.optional(), + disableBaseConfig: z.boolean().optional() }) export type CircleCiOptions = z.infer diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index e4b918878..f919cdf5f 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -410,25 +410,25 @@ export default class CircleCi extends Hook generateConfig(): CircleCIState { if (!this.generatedConfig) { - const generated = { - executors: Object.fromEntries( - this.options.executors?.map( - (executor) => [executor.name, { docker: [{ image: executor.image }] }], - {} - ) ?? [] - ), - workflows: Object.fromEntries( - this.options.workflows?.map((workflow) => { + const generated: CircleCIStatePartial = {} + if (this.options.executors) { + generated.executors = Object.fromEntries( + this.options.executors.map((executor) => [executor.name, { docker: [{ image: executor.image }] }]) + ) + } + if (this.options.workflows) { + generated.workflows = Object.fromEntries( + this.options.workflows.map((workflow) => { const generatedJobs = { jobs: generateJobs(workflow) } return [workflow.name, mergeWithConcatenatedArrays(generatedJobs, workflow.custom)] - }) ?? [] + }) ) - } satisfies CircleCIStatePartial + } this.generatedConfig = mergeWithConcatenatedArrays( {}, - getBaseConfig(), + this.options.disableBaseConfig ? {} : getBaseConfig(), generated, this.options.custom ?? {} ) diff --git a/plugins/circleci/test/circleci-config.test.ts b/plugins/circleci/test/circleci-config.test.ts index f70765430..3b3d763d7 100644 --- a/plugins/circleci/test/circleci-config.test.ts +++ b/plugins/circleci/test/circleci-config.test.ts @@ -46,7 +46,8 @@ const anotherTestWorkflowJob: CircleCiWorkflowJob = { } const simpleOptions: CircleCiOptions = { jobs: [testJob], - workflows: [{ name: 'tool-kit', jobs: [testWorkflowJob] }] + workflows: [{ name: 'tool-kit', jobs: [testWorkflowJob] }], + disableBaseConfig: true } describe('CircleCI config hook', () => { @@ -61,10 +62,10 @@ describe('CircleCI config hook', () => { process.chdir(originalDir) }) - describe.skip('check', () => { + describe('isInstalled', () => { it('should return true if the hook job is in the circleci workflow', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) - const hook = new CircleCi(logger, 'CircleCi', {}) + const hook = new CircleCi(logger, 'CircleCi', simpleOptions) expect(await hook.isInstalled()).toBeTruthy() }) @@ -76,7 +77,7 @@ describe('CircleCI config hook', () => { it('should return false if the base configuration is missing', async () => { process.chdir(path.join(__dirname, 'files', 'with-hook')) - const hook = new CircleCi(logger, 'CircleCi', simpleOptions) + const hook = new CircleCi(logger, 'CircleCi', { ...simpleOptions, disableBaseConfig: false }) expect(await hook.isInstalled()).toBeFalsy() }) }) diff --git a/plugins/circleci/test/files/with-hook/.circleci/config.yml b/plugins/circleci/test/files/with-hook/.circleci/config.yml index ee711cdd8..b4b551f13 100644 --- a/plugins/circleci/test/files/with-hook/.circleci/config.yml +++ b/plugins/circleci/test/files/with-hook/.circleci/config.yml @@ -1,20 +1,8 @@ workflows: tool-kit: jobs: - - test-job: - name: test-job-node + - tool-kit/test-job: requires: - waiting-for-approval - - that-job-node - executor: node - filters: - tags: - only: /^v\d+\.\d+\.\d+(-.+)?/ - nightly: - jobs: - - test-job: - name: test-job-node - requires: - - waiting-for-approval - - that-job-node + - tool-kit/that-job-node executor: node From c7bf88743ee9598002cc8181d173457171a804f0 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Fri, 12 Apr 2024 15:39:18 +0100 Subject: [PATCH 130/321] build(circleci): make all the plugin's Tool Kit deps explicit --- package-lock.json | 87 +++++++++++++++++----------------- plugins/circleci/package.json | 4 ++ plugins/circleci/tsconfig.json | 21 +++++--- 3 files changed, 62 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index a2e70080a..5c6ec9d46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -93,7 +93,7 @@ "zod": "^3.22.4" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -180,7 +180,7 @@ "type-fest": "^3.13.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -1092,6 +1092,7 @@ "core/sandbox": { "name": "@financial-times/sandbox", "version": "1.0.0", + "extraneous": true, "license": "ISC", "dependencies": { "@dotcom-tool-kit/base": "file:../../lib/base", @@ -1230,7 +1231,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -1247,7 +1248,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -1273,7 +1274,7 @@ "@types/triple-beam": "^1.3.2" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -1291,7 +1292,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -1392,7 +1393,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -1458,7 +1459,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -1481,7 +1482,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" } }, @@ -6637,10 +6638,6 @@ "version": "3.0.0", "license": "MIT" }, - "node_modules/@financial-times/sandbox": { - "resolved": "core/sandbox", - "link": true - }, "node_modules/@gar/promisify": { "version": "1.1.3", "license": "MIT" @@ -29184,7 +29181,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29205,7 +29202,7 @@ "@dotcom-tool-kit/backend-heroku-app": "^3.1.4" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29223,7 +29220,7 @@ "@dotcom-tool-kit/npm": "^3.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29241,7 +29238,7 @@ "@dotcom-tool-kit/serverless": "^2.4.4" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29254,8 +29251,10 @@ "license": "ISC", "dependencies": { "@dotcom-tool-kit/base": "^3.4.1", + "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/state": "^3.3.0", "jest-diff": "^29.5.0", "lodash": "^4.17.21", @@ -29264,6 +29263,8 @@ "yaml": "^2.1.1" }, "devDependencies": { + "@dotcom-tool-kit/plugin": "^1.0.0", + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/jest": "^27.4.0", "@types/js-yaml": "^4.0.3", @@ -29272,7 +29273,7 @@ "zod": "^3.22.4" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29292,7 +29293,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29314,7 +29315,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29336,7 +29337,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29456,7 +29457,7 @@ "@dotcom-tool-kit/npm": "^3.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29477,7 +29478,7 @@ "@dotcom-tool-kit/schemas": "^1.0.0" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29502,7 +29503,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29717,7 +29718,7 @@ "@dotcom-tool-kit/webpack": "^3.2.0" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29752,7 +29753,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29773,7 +29774,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29801,7 +29802,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29826,7 +29827,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29844,7 +29845,7 @@ "tslib": "^2.3.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29930,7 +29931,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -29961,7 +29962,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30082,7 +30083,7 @@ "@dotcom-tool-kit/schemas": "^1.0.0" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30216,7 +30217,7 @@ "@dotcom-tool-kit/schemas": "^1.0.0" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30245,7 +30246,7 @@ "@types/nodemon": "^1.19.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30282,7 +30283,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30488,7 +30489,7 @@ "@types/pa11y": "^5.3.4" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30520,7 +30521,7 @@ "zod": "^3.22.4" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30554,7 +30555,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30609,7 +30610,7 @@ "@dotcom-tool-kit/schemas": "^1.0.0" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30637,7 +30638,7 @@ "winston": "^3.8.2" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30854,7 +30855,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { @@ -30885,7 +30886,7 @@ "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" }, "peerDependencies": { diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 1ccbbc53a..c9ae34955 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -8,8 +8,10 @@ }, "dependencies": { "@dotcom-tool-kit/base": "^3.4.1", + "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/options": "^3.2.0", "@dotcom-tool-kit/state": "^3.3.0", "jest-diff": "^29.5.0", "lodash": "^4.17.21", @@ -28,6 +30,8 @@ "bugs": "https://github.com/financial-times/dotcom-tool-kit/issues", "homepage": "https://github.com/financial-times/dotcom-tool-kit/tree/main/plugins/circleci", "devDependencies": { + "@dotcom-tool-kit/plugin": "^1.0.0", + "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/jest": "^27.4.0", "@types/js-yaml": "^4.0.3", diff --git a/plugins/circleci/tsconfig.json b/plugins/circleci/tsconfig.json index b9d99f9a1..c92951d9d 100644 --- a/plugins/circleci/tsconfig.json +++ b/plugins/circleci/tsconfig.json @@ -2,26 +2,33 @@ "extends": "../../tsconfig.settings.json", "references": [ { - "path": "../../lib/error" + "path": "../../lib/base" }, { - "path": "../../lib/state" + "path": "../../lib/conflict" }, { - "path": "../../lib/logger" + "path": "../../lib/error" }, { - "path": "../../lib/base" + "path": "../../lib/logger" }, { "path": "../../lib/options" + }, + { + "path": "../../lib/plugin" + }, + { + "path": "../../lib/schemas" + }, + { + "path": "../../lib/state" } ], "compilerOptions": { "outDir": "lib", "rootDir": "src" }, - "include": [ - "src/**/*" - ] + "include": ["src/**/*"] } From f25a00a088c65f7651991eabd829ddfc628a4c53 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Mon, 15 Apr 2024 12:28:23 +0100 Subject: [PATCH 131/321] refactor(circleci): try to make new code more readable --- lib/schemas/src/hooks/circleci.ts | 5 ++ plugins/circleci/src/circleci-config.ts | 62 ++++++++++++++++--------- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/lib/schemas/src/hooks/circleci.ts b/lib/schemas/src/hooks/circleci.ts index 68d92de4c..ed84d087e 100644 --- a/lib/schemas/src/hooks/circleci.ts +++ b/lib/schemas/src/hooks/circleci.ts @@ -5,11 +5,13 @@ export const CircleCiExecutor = z.object({ image: z.string() }) export type CircleCiExecutor = z.infer + export const CircleCiJob = z.object({ name: z.string(), command: z.string() }) export type CircleCiJob = z.infer + export const CircleCiWorkflowJob = z.object({ name: z.string(), requires: z.array(z.string()), @@ -17,6 +19,7 @@ export const CircleCiWorkflowJob = z.object({ custom: z.unknown().optional() }) export type CircleCiWorkflowJob = z.infer + export const CircleCiWorkflow = z.object({ name: z.string(), jobs: z.array(CircleCiWorkflowJob), @@ -24,8 +27,10 @@ export const CircleCiWorkflow = z.object({ custom: z.unknown().optional() }) export type CircleCiWorkflow = z.infer + export const CircleCiCustomConfig = z.record(z.unknown()) export type CircleCiCustomConfig = z.infer + export const CircleCiSchema = z.object({ executors: z.array(CircleCiExecutor).optional(), jobs: z.array(CircleCiJob).optional(), diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index f919cdf5f..365c22453 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -113,6 +113,8 @@ const matrixBoilerplate = () => ({ */ export const tagFilter = { filters: { tags: { only: `${/^v\d+\.\d+\.\d+(-.+)?/}` } } } +// helper override to the Lodash mergeWith function with a pre-defined +// customiser that will concatenate arrays rather than overriding them by index const mergeWithConcatenatedArrays = (arg0: unknown, ...args: unknown[]) => mergeWith(arg0, ...args, (obj: unknown, source: unknown) => { if (Array.isArray(obj)) { @@ -244,27 +246,52 @@ const installationsOverlap = ( rootOptionOverlaps(installation.options?.[rootOption] ?? [], other.options?.[rootOption] ?? []) ) +// classify installation as either mergeable or unmergeable, and mark any other +// installations that overlap with it as now unmergeable const partitionInstallations = ( installation: HookInstallation, - mergeable: HookInstallation[], - unmergeable: HookInstallation[] + currentlyMergeable: HookInstallation[], + currentlyUnmergeable: HookInstallation[] ): [HookInstallation[], HookInstallation[]] => { - const [noLongerMergeable, stillMergeable] = partition(mergeable, (other) => + const [noLongerMergeable, mergeable] = partition(currentlyMergeable, (other) => installationsOverlap(installation, other) ) + const unmergeable = currentlyUnmergeable.concat(noLongerMergeable) - const overlapsWithUnmergeable = unmergeable.some((other) => installationsOverlap(installation, other)) - + const overlapsWithUnmergeable = currentlyUnmergeable.some((other) => + installationsOverlap(installation, other) + ) if (noLongerMergeable.length > 0 || overlapsWithUnmergeable) { - return [stillMergeable, [...unmergeable, ...noLongerMergeable, installation]] + unmergeable.push(installation) + } else { + mergeable.push(installation) } - return [[...stillMergeable, installation], unmergeable] + return [mergeable, unmergeable] } +// find any items with the same value in their 'name' field and merge those +// together const mergeRootOptions = (options: T[]): T[] => Object.values(groupBy(options, 'name')).map((matching) => mergeWithConcatenatedArrays({}, ...matching)) +const mergeInstallations = (installations: HookInstallation[]): CircleCiOptions => ({ + // merge each of the root options ('executors', 'jobs', 'workflows') using + // their 'name' keys + ...Object.fromEntries( + rootOptionKeys.map((rootKey) => { + // flatten each installation's options into a single array (the order of + // the installations in the array is maintained) + const rootOptions = installations.flatMap<{ name: string }>( + (installation) => installation.options[rootKey] ?? [] + ) + return [rootKey, mergeRootOptions(rootOptions)] + }) + ), + // squash all the custom options together + custom: mergeWithConcatenatedArrays({}, ...installations.map((installation) => installation.options.custom)) +}) + const mergeInstallationResults = ( plugin: Plugin, mergeable: HookInstallation[], @@ -277,20 +304,7 @@ const mergeInstallationResults = ( plugin, forHook: 'CircleCi', hookConstructor: CircleCi, - options: { - ...Object.fromEntries( - rootOptionKeys.map((rootKey) => { - const rootOptions = mergeable.flatMap<{ name: string }>( - (installation) => installation.options[rootKey] ?? [] - ) - return [rootKey, mergeRootOptions(rootOptions)] - }) - ), - custom: mergeWithConcatenatedArrays( - {}, - ...mergeable.map((installation) => installation.options.custom) - ) - } + options: mergeInstallations(mergeable) }) } @@ -311,6 +325,8 @@ const generateJobs = (workflow: CircleCiWorkflow): Job[] => const splitIntoMatrix = job.splitIntoMatrix ?? true return { [toolKitOrbPrefix(job.name)]: merge( + // repeatedly check splitIntoMatrix in different arguments so we can + // generate config with a nice order of keys splitIntoMatrix ? { name: `tool-kit/${job.name}-<< matrix.executor >>` } : {}, { requires: job.requires.map((required) => { @@ -318,6 +334,8 @@ const generateJobs = (workflow: CircleCiWorkflow): Job[] => return required } const requiredOrb = toolKitOrbPrefix(required) + // only need to include a suffix for the required job if it splits + // into a matrix for Node versions const splitRequiredIntoMatrix = workflow.jobs?.find(({ name: jobName }) => required === jobName)?.splitIntoMatrix ?? true if (!splitRequiredIntoMatrix) { @@ -368,6 +386,8 @@ export default class CircleCi extends Hook [HookInstallation[], HookInstallation[]] >( ([mergeable, unmergeable], installation) => { + // a conflicting installation is marked as unmergeable without + // affecting the mergeability of the other installations if (isConflict(installation)) { return [mergeable, [...unmergeable, ...installation.conflicting]] } else { From ce7d9c254f8a5c075377b8846fe6c63a10567566 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Mon, 15 Apr 2024 18:10:49 +0100 Subject: [PATCH 132/321] feat(circleci): don't generate matrices if only one Node version used This creates much simpler config for the majority of projects (i.e., projects that don't need to test against multiple versions of Node.) --- plugins/circleci/src/circleci-config.ts | 51 +++++++------------ plugins/circleci/test/circleci-config.test.ts | 2 +- .../test/files/with-hook/.circleci/config.yml | 2 +- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/plugins/circleci/src/circleci-config.ts b/plugins/circleci/src/circleci-config.ts index 365c22453..a44871d69 100644 --- a/plugins/circleci/src/circleci-config.ts +++ b/plugins/circleci/src/circleci-config.ts @@ -93,13 +93,8 @@ const getNodeVersions = (): Array => { const nodeVersionToExecutor = (version: string, index: number): string => index === 0 ? 'node' : `node${version.replaceAll('.', '_')}` -// These boilerplate objects are (typically) needed for each job. They can be -// spread into your custom config, and are automatically included when calling -// generateSimpleJob. - -// Needs to be lazy as the node versions haven't been loaded yet when this -// module is initialised. -const matrixBoilerplate = () => ({ +const matrixBoilerplate = (jobName: string) => ({ + name: `${jobName}-<< matrix.executor >>`, matrix: { parameters: { executor: getNodeVersions().map(nodeVersionToExecutor) @@ -123,6 +118,8 @@ const mergeWithConcatenatedArrays = (arg0: unknown, ...args: unknown[]) => }) const getBaseConfig = (): CircleCIState => { + const runsOnMultipleNodeVersions = getNodeVersions().length > 1 + const setupMatrix = runsOnMultipleNodeVersions ? matrixBoilerplate('tool-kit/setup') : { executor: 'node' } return { version: 2.1, orbs: { @@ -168,9 +165,8 @@ const getBaseConfig = (): CircleCIState => { }, { 'tool-kit/setup': { - name: 'tool-kit/setup-<< matrix.executor >>', + ...setupMatrix, requires: ['checkout', 'waiting-for-approval'], - ...matrixBoilerplate(), ...tagFilter } } @@ -187,16 +183,7 @@ const getBaseConfig = (): CircleCIState => { } ] }, - jobs: [ - 'checkout', - { - 'tool-kit/setup': { - name: 'tool-kit/setup-<< matrix.executor >>', - requires: ['checkout'], - ...matrixBoilerplate() - } - } - ] + jobs: ['checkout', { 'tool-kit/setup': { ...setupMatrix, requires: ['checkout'] } }] } } } @@ -320,14 +307,17 @@ const mergeInstallationResults = ( const toolKitOrbPrefix = (job: string) => `tool-kit/${job}` -const generateJobs = (workflow: CircleCiWorkflow): Job[] => - workflow.jobs.map((job) => { - const splitIntoMatrix = job.splitIntoMatrix ?? true +const generateJobs = (workflow: CircleCiWorkflow): Job[] => { + const runsOnMultipleNodeVersions = getNodeVersions().length > 1 + return workflow.jobs.map((job) => { + const splitIntoMatrix = runsOnMultipleNodeVersions && (job.splitIntoMatrix ?? true) return { [toolKitOrbPrefix(job.name)]: merge( - // repeatedly check splitIntoMatrix in different arguments so we can - // generate config with a nice order of keys - splitIntoMatrix ? { name: `tool-kit/${job.name}-<< matrix.executor >>` } : {}, + splitIntoMatrix + ? matrixBoilerplate(job.name) + : { + executor: 'node' + }, { requires: job.requires.map((required) => { if (['checkout', 'waiting-for-approval'].includes(required)) { @@ -337,25 +327,20 @@ const generateJobs = (workflow: CircleCiWorkflow): Job[] => // only need to include a suffix for the required job if it splits // into a matrix for Node versions const splitRequiredIntoMatrix = - workflow.jobs?.find(({ name: jobName }) => required === jobName)?.splitIntoMatrix ?? true + runsOnMultipleNodeVersions && + (workflow.jobs?.find(({ name: jobName }) => required === jobName)?.splitIntoMatrix ?? true) if (!splitRequiredIntoMatrix) { return requiredOrb } return `${requiredOrb}-${splitIntoMatrix ? '<< matrix.executor >>' : 'node'}` }) }, - splitIntoMatrix - ? { - matrix: { parameters: { executor: getNodeVersions().map(nodeVersionToExecutor) } } - } - : { - executor: 'node' - }, workflow.runOnRelease ? tagFilter : {}, job.custom ) } }) +} export default class CircleCi extends Hook { circleConfigPath = path.resolve(process.cwd(), '.circleci/config.yml') diff --git a/plugins/circleci/test/circleci-config.test.ts b/plugins/circleci/test/circleci-config.test.ts index 3b3d763d7..355342de4 100644 --- a/plugins/circleci/test/circleci-config.test.ts +++ b/plugins/circleci/test/circleci-config.test.ts @@ -116,7 +116,7 @@ describe('CircleCI config hook', () => { jobs: expect.arrayContaining([ expect.objectContaining({ 'tool-kit/test-job': expect.objectContaining({ - requires: ['waiting-for-approval', 'tool-kit/that-job-node'] + requires: ['waiting-for-approval', 'tool-kit/that-job'] }) }) ]) diff --git a/plugins/circleci/test/files/with-hook/.circleci/config.yml b/plugins/circleci/test/files/with-hook/.circleci/config.yml index b4b551f13..63bea46ef 100644 --- a/plugins/circleci/test/files/with-hook/.circleci/config.yml +++ b/plugins/circleci/test/files/with-hook/.circleci/config.yml @@ -4,5 +4,5 @@ workflows: - tool-kit/test-job: requires: - waiting-for-approval - - tool-kit/that-job-node + - tool-kit/that-job executor: node From f707366f27e6a38175afa7dbf2a549c0ba8f67b7 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 15 Jan 2024 11:46:20 +0000 Subject: [PATCH 133/321] feat!: move babel options to task options and allow configuring env --- lib/schemas/src/plugins.ts | 2 - lib/schemas/src/tasks.ts | 5 +-- lib/schemas/src/{plugins => tasks}/babel.ts | 4 +- plugins/babel/.toolkitrc.yml | 9 ++-- plugins/babel/src/run-babel.ts | 47 ------------------- plugins/babel/src/tasks/babel.ts | 50 +++++++++++++++++++++ plugins/babel/src/tasks/development.ts | 11 ----- plugins/babel/src/tasks/production.ts | 11 ----- 8 files changed, 59 insertions(+), 80 deletions(-) rename lib/schemas/src/{plugins => tasks}/babel.ts (67%) delete mode 100644 plugins/babel/src/run-babel.ts create mode 100644 plugins/babel/src/tasks/babel.ts delete mode 100644 plugins/babel/src/tasks/development.ts delete mode 100644 plugins/babel/src/tasks/production.ts diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 7d1559cb5..2900cecc6 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -1,4 +1,3 @@ -import { BabelSchema } from './plugins/babel' import { CircleCISchema } from './plugins/circleci' import { CypressSchema } from './plugins/cypress' import { DopplerSchema } from './plugins/doppler' @@ -23,7 +22,6 @@ import { type InferSchemaOptions } from './infer' export const PluginSchemas = { 'app root': RootSchema, - '@dotcom-tool-kit/babel': BabelSchema, '@dotcom-tool-kit/circleci': CircleCISchema, '@dotcom-tool-kit/cypress': CypressSchema, '@dotcom-tool-kit/doppler': DopplerSchema, diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 3a8cf9b71..44202b2d5 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -1,9 +1,8 @@ -import { z } from 'zod' - import { type InferSchemaOptions } from './infer' +import { BabelSchema } from './tasks/babel' export const TaskSchemas = { - 'fake schema': z.never() + Babel: BabelSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/babel.ts b/lib/schemas/src/tasks/babel.ts similarity index 67% rename from lib/schemas/src/plugins/babel.ts rename to lib/schemas/src/tasks/babel.ts index 98d52730f..d7bfed739 100644 --- a/lib/schemas/src/plugins/babel.ts +++ b/lib/schemas/src/tasks/babel.ts @@ -3,8 +3,10 @@ import { z } from 'zod' export const BabelSchema = z.object({ files: z.string().optional(), outputPath: z.string().optional(), - configFile: z.string().optional() + configFile: z.string().optional(), + envName: z.union([z.literal('production'), z.literal('development')]) }) + export type BabelOptions = z.infer export const Schema = BabelSchema diff --git a/plugins/babel/.toolkitrc.yml b/plugins/babel/.toolkitrc.yml index 8f5d2558f..ba5da3398 100644 --- a/plugins/babel/.toolkitrc.yml +++ b/plugins/babel/.toolkitrc.yml @@ -1,10 +1,9 @@ tasks: - BabelDevelopment: './lib/tasks/development' - BabelProduction: './lib/tasks/production' + Babel: './lib/tasks/babel' commands: - 'build:local': BabelDevelopment - 'build:ci': BabelProduction - 'build:remote': BabelProduction + 'build:local': Babel + 'build:ci': Babel + 'build:remote': Babel version: 2 diff --git a/plugins/babel/src/run-babel.ts b/plugins/babel/src/run-babel.ts deleted file mode 100644 index 15ac35de6..000000000 --- a/plugins/babel/src/run-babel.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { ToolKitError } from '@dotcom-tool-kit/error' -import { hookConsole } from '@dotcom-tool-kit/logger' -import type { BabelOptions } from '@dotcom-tool-kit/schemas/lib/plugins/babel' -import * as babel from '@babel/core' -import fg from 'fast-glob' -import { promises as fs } from 'fs' -import path from 'path' -import type { Logger } from 'winston' - -export async function runBabel( - logger: Logger, - options: BabelOptions, - transformOptions?: babel.TransformOptions -): Promise { - const fileGlob = options.files ?? 'src/**/*.js' - const files = await fg(fileGlob) - // Work out the root of the glob so we can strip this part of the path out of - // the outputted files. - // E.g., a glob of 'src/**/*.js' = src/a/b.js -> lib/a/b.js - // a glob of 'src/a/**/*.js' = src/a/b.js -> lib/b.js - const { base } = fg.generateTasks(fileGlob)[0] - - const outputPath = options.outputPath ?? 'lib' - - if (options.configFile) { - const { configFile } = options - transformOptions = transformOptions ? { ...transformOptions, configFile } : { configFile } - } - - logger.info('running babel') - const unhook = hookConsole(logger, 'babel') - await Promise.all( - files.map(async (file) => { - const transformed = await babel.transformFileAsync(file, transformOptions) - if (!transformed?.code) { - const error = new ToolKitError('Babel failed to generate code') - error.details = `the problematic file was ${file}` - throw error - } - // Create parent directories if they don't exist before creating child file of transpiled code. - const filePath = path.join(outputPath, path.relative(base, file)) - await fs.mkdir(path.dirname(filePath), { recursive: true }) - await fs.writeFile(filePath, transformed.code) - }) - ) - unhook() -} diff --git a/plugins/babel/src/tasks/babel.ts b/plugins/babel/src/tasks/babel.ts new file mode 100644 index 000000000..140e83fb8 --- /dev/null +++ b/plugins/babel/src/tasks/babel.ts @@ -0,0 +1,50 @@ +import { promises as fs } from 'fs' +import path from 'path' + +import * as babel from '@babel/core' +import fg from 'fast-glob' + +import { type BabelSchema } from '@dotcom-tool-kit/schemas/lib/tasks/babel' +import { Task } from '@dotcom-tool-kit/base' +import { ToolKitError } from '@dotcom-tool-kit/error' +import { hookConsole } from '@dotcom-tool-kit/logger' + +export default class Babel extends Task<{ task: typeof BabelSchema }> { + static description = 'build babel' + + async run(): Promise { + const fileGlob = this.options.files ?? 'src/**/*.js' + const files = await fg(fileGlob) + // Work out the root of the glob so we can strip this part of the path out of + // the outputted files. + // E.g., a glob of 'src/**/*.js' = src/a/b.js -> lib/a/b.js + // a glob of 'src/a/**/*.js' = src/a/b.js -> lib/b.js + const { base } = fg.generateTasks(fileGlob)[0] + + const outputPath = this.options.outputPath ?? 'lib' + + this.logger.info('running babel') + const unhook = hookConsole(this.logger, 'babel') + + await Promise.all( + files.map(async (file) => { + const transformed = await babel.transformFileAsync(file, { + configFile: this.options.configFile, + envName: this.options.envName + }) + // TODO better error handling + if (!transformed?.code) { + const error = new ToolKitError('Babel failed to generate code') + error.details = `the problematic file was ${file}` + throw error + } + // Create parent directories if they don't exist before creating child file of transpiled code. + const filePath = path.join(outputPath, path.relative(base, file)) + await fs.mkdir(path.dirname(filePath), { recursive: true }) + await fs.writeFile(filePath, transformed.code) + }) + ) + + unhook() + } +} diff --git a/plugins/babel/src/tasks/development.ts b/plugins/babel/src/tasks/development.ts deleted file mode 100644 index 1aed636af..000000000 --- a/plugins/babel/src/tasks/development.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { runBabel } from '../run-babel' -import { Task } from '@dotcom-tool-kit/base' -import { BabelSchema } from '@dotcom-tool-kit/schemas/lib/plugins/babel' - -export default class BabelDevelopment extends Task<{ plugin: typeof BabelSchema }> { - static description = 'build babel' - - async run(): Promise { - await runBabel(this.logger, this.pluginOptions) - } -} diff --git a/plugins/babel/src/tasks/production.ts b/plugins/babel/src/tasks/production.ts deleted file mode 100644 index b20a290e3..000000000 --- a/plugins/babel/src/tasks/production.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { runBabel } from '../run-babel' -import { Task } from '@dotcom-tool-kit/base' -import { BabelSchema } from '@dotcom-tool-kit/schemas/lib/plugins/babel' - -export default class BabelProduction extends Task<{ plugin: typeof BabelSchema }> { - static description = 'build babel' - - async run(): Promise { - await runBabel(this.logger, this.pluginOptions, { envName: 'production' }) - } -} From d9a0d62633875ca198308dae3e0e2fa35cd7c621 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 15 Jan 2024 16:05:43 +0000 Subject: [PATCH 134/321] feat!: move eslint plugin options to task options also removes the "options" option, which is only used by our own tests (not any apps!) and goes against our current philosophy of not exposing every option via toolkitrc --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/plugins/eslint.ts | 10 ---------- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/tasks/eslint.ts | 9 +++++++++ plugins/eslint/src/tasks/eslint.ts | 8 ++++---- 5 files changed, 16 insertions(+), 17 deletions(-) delete mode 100644 lib/schemas/src/plugins/eslint.ts create mode 100644 lib/schemas/src/tasks/eslint.ts diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 2900cecc6..af7995c6e 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -2,7 +2,6 @@ import { CircleCISchema } from './plugins/circleci' import { CypressSchema } from './plugins/cypress' import { DopplerSchema } from './plugins/doppler' import { RootSchema } from './plugins/dotcom-tool-kit' -import { ESLintSchema } from './plugins/eslint' import { HerokuSchema } from './plugins/heroku' import { LintStagedNpmSchema } from './plugins/lint-staged-npm' import { JestSchema } from './plugins/jest' @@ -25,7 +24,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/circleci': CircleCISchema, '@dotcom-tool-kit/cypress': CypressSchema, '@dotcom-tool-kit/doppler': DopplerSchema, - '@dotcom-tool-kit/eslint': ESLintSchema, '@dotcom-tool-kit/heroku': HerokuSchema, '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, '@dotcom-tool-kit/jest': JestSchema, diff --git a/lib/schemas/src/plugins/eslint.ts b/lib/schemas/src/plugins/eslint.ts deleted file mode 100644 index 4e11c42e6..000000000 --- a/lib/schemas/src/plugins/eslint.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { z } from 'zod' - -export const ESLintSchema = z.object({ - files: z.string().array().or(z.string()).default(['**/*.js']), - config: z.record(z.unknown()).optional(), // @deprecated: use options instead - options: z.record(z.unknown()).optional() -}) -export type ESLintOptions = z.infer - -export const Schema = ESLintSchema diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 44202b2d5..0ebf1ee72 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -1,8 +1,10 @@ import { type InferSchemaOptions } from './infer' import { BabelSchema } from './tasks/babel' +import { ESLintSchema } from './tasks/eslint' export const TaskSchemas = { - Babel: BabelSchema + Babel: BabelSchema, + Eslint: ESLintSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/tasks/eslint.ts b/lib/schemas/src/tasks/eslint.ts new file mode 100644 index 000000000..1941da917 --- /dev/null +++ b/lib/schemas/src/tasks/eslint.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' + +export const ESLintSchema = z.object({ + files: z.string().array().or(z.string()).default(['**/*.js']) +}) + +export type ESLintOptions = z.infer + +export const Schema = ESLintSchema diff --git a/plugins/eslint/src/tasks/eslint.ts b/plugins/eslint/src/tasks/eslint.ts index 7ed567fad..b130e5d0f 100644 --- a/plugins/eslint/src/tasks/eslint.ts +++ b/plugins/eslint/src/tasks/eslint.ts @@ -1,15 +1,15 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { styles } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' -import { ESLintSchema } from '@dotcom-tool-kit/schemas/lib/plugins/eslint' +import { ESLintSchema } from '@dotcom-tool-kit/schemas/lib/tasks/eslint' import { ESLint } from 'eslint' -export default class Eslint extends Task<{ plugin: typeof ESLintSchema }> { +export default class Eslint extends Task<{ task: typeof ESLintSchema }> { static description = '' async run(files?: string[]): Promise { - const eslint = new ESLint(this.pluginOptions.options) - const results = await eslint.lintFiles(files ?? this.pluginOptions.files) + const eslint = new ESLint() + const results = await eslint.lintFiles(files ?? this.options.files) const formatter = await eslint.loadFormatter('stylish') const resultText = formatter.format(results) From 29ed0f2843b97732379cdf2c342de8e6ed748409 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 14:54:21 +0100 Subject: [PATCH 135/321] feat!: move jest options to task options and allow configuring env --- lib/schemas/src/plugins.ts | 2 - lib/schemas/src/tasks.ts | 4 +- lib/schemas/src/{plugins => tasks}/jest.ts | 5 ++- plugins/jest/.toolkitrc.yml | 7 ++- plugins/jest/src/tasks/ci.ts | 11 ----- .../jest/src/{run-jest.ts => tasks/jest.ts} | 45 +++++++++++-------- plugins/jest/src/tasks/local.ts | 11 ----- 7 files changed, 35 insertions(+), 50 deletions(-) rename lib/schemas/src/{plugins => tasks}/jest.ts (62%) delete mode 100644 plugins/jest/src/tasks/ci.ts rename plugins/jest/src/{run-jest.ts => tasks/jest.ts} (55%) delete mode 100644 plugins/jest/src/tasks/local.ts diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index af7995c6e..7d64b6344 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -4,7 +4,6 @@ import { DopplerSchema } from './plugins/doppler' import { RootSchema } from './plugins/dotcom-tool-kit' import { HerokuSchema } from './plugins/heroku' import { LintStagedNpmSchema } from './plugins/lint-staged-npm' -import { JestSchema } from './plugins/jest' import { MochaSchema } from './plugins/mocha' import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' @@ -26,7 +25,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/doppler': DopplerSchema, '@dotcom-tool-kit/heroku': HerokuSchema, '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, - '@dotcom-tool-kit/jest': JestSchema, '@dotcom-tool-kit/mocha': MochaSchema, '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 0ebf1ee72..dbbc6b4de 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -1,10 +1,12 @@ import { type InferSchemaOptions } from './infer' import { BabelSchema } from './tasks/babel' import { ESLintSchema } from './tasks/eslint' +import { JestSchema } from './tasks/jest' export const TaskSchemas = { Babel: BabelSchema, - Eslint: ESLintSchema + Eslint: ESLintSchema, + Jest: JestSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/jest.ts b/lib/schemas/src/tasks/jest.ts similarity index 62% rename from lib/schemas/src/plugins/jest.ts rename to lib/schemas/src/tasks/jest.ts index a14ff44b0..9d0e5187a 100644 --- a/lib/schemas/src/plugins/jest.ts +++ b/lib/schemas/src/tasks/jest.ts @@ -1,9 +1,10 @@ import { z } from 'zod' export const JestSchema = z.object({ - configPath: z.string().optional() + configPath: z.string().optional(), + mode: z.union([z.literal('ci'), z.literal('local')]) }) -export type JestMode = 'ci' | 'local' + export type JestOptions = z.infer export const Schema = JestSchema diff --git a/plugins/jest/.toolkitrc.yml b/plugins/jest/.toolkitrc.yml index 46d3ab103..6ae2716b0 100644 --- a/plugins/jest/.toolkitrc.yml +++ b/plugins/jest/.toolkitrc.yml @@ -1,9 +1,8 @@ tasks: - JestLocal: './lib/tasks/local' - JestCI: './lib/tasks/ci' + Jest: './lib/tasks/jest' commands: - 'test:local': JestLocal - 'test:ci': JestCI + 'test:local': Jest + 'test:ci': Jest # TODO provide default mode option here version: 2 diff --git a/plugins/jest/src/tasks/ci.ts b/plugins/jest/src/tasks/ci.ts deleted file mode 100644 index aa64ce927..000000000 --- a/plugins/jest/src/tasks/ci.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Task } from '@dotcom-tool-kit/base' -import { JestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/jest' -import runJest from '../run-jest' - -export default class JestCI extends Task<{ plugin: typeof JestSchema }> { - static description = '' - - async run(): Promise { - await runJest(this.logger, 'ci', this.pluginOptions) - } -} diff --git a/plugins/jest/src/run-jest.ts b/plugins/jest/src/tasks/jest.ts similarity index 55% rename from plugins/jest/src/run-jest.ts rename to plugins/jest/src/tasks/jest.ts index 239030774..a0dbae631 100644 --- a/plugins/jest/src/run-jest.ts +++ b/plugins/jest/src/tasks/jest.ts @@ -1,8 +1,9 @@ +import { Task } from '@dotcom-tool-kit/base' +import { JestSchema } from '@dotcom-tool-kit/schemas/lib/tasks/jest' import { fork } from 'node:child_process' import { readFile } from 'node:fs/promises' -import type { JestOptions, JestMode } from '@dotcom-tool-kit/schemas/lib/plugins/jest' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' -import type { Logger } from 'winston' + const jestCLIPath = require.resolve('jest-cli/bin/jest') // By default Jest will choose the number of worker threads based on the number @@ -28,23 +29,29 @@ async function guessVCpus(): Promise { } } -export default async function runJest(logger: Logger, mode: JestMode, options: JestOptions): Promise { - const args = ['--colors', options.configPath ? `--config=${options.configPath}` : ''] - // TODO:20231107:IM we should probably refactor this plugin to move - // CI-specific logic to be within the CI task module - if (mode === 'ci') { - args.push('--ci') - // only relevant if running on CircleCI, other CI environments might handle - // virtualisation completely differently - if (process.env.CIRCLECI) { - // leave one vCPU free for the main thread, same as the default Jest - // logic - const maxWorkers = (await guessVCpus()) - 1 - args.push(`--max-workers=${maxWorkers}`) +export default class Jest extends Task<{ task: typeof JestSchema }> { + static description = '' + + async run(): Promise { + const args = ['--colors', this.options.configPath ? `--config=${this.options.configPath}` : ''] + + // TODO:20231107:IM we should probably refactor this plugin to move + // CI-specific logic to be within the CI task module + if (this.options.mode === 'ci') { + args.push('--ci') + // only relevant if running on CircleCI, other CI environments might handle + // virtualisation completely differently + if (process.env.CIRCLECI) { + // leave one vCPU free for the main thread, same as the default Jest + // logic + const maxWorkers = (await guessVCpus()) - 1 + args.push(`--max-workers=${maxWorkers}`) + } } + + this.logger.info(`running jest ${args.join(' ')}`) + const child = fork(jestCLIPath, args, { silent: true }) + hookFork(this.logger, 'jest', child) + return waitOnExit('jest', child) } - logger.info(`running jest ${args.join(' ')}`) - const child = fork(jestCLIPath, args, { silent: true }) - hookFork(logger, 'jest', child) - return waitOnExit('jest', child) } diff --git a/plugins/jest/src/tasks/local.ts b/plugins/jest/src/tasks/local.ts deleted file mode 100644 index 4cb4ea96a..000000000 --- a/plugins/jest/src/tasks/local.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Task } from '@dotcom-tool-kit/base' -import { JestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/jest' -import runJest from '../run-jest' - -export default class JestLocal extends Task<{ plugin: typeof JestSchema }> { - static description = '' - - async run(): Promise { - await runJest(this.logger, 'local', this.pluginOptions) - } -} From 08b092bc1f3af5ee56413f17a7affdab3eed057e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:21:39 +0100 Subject: [PATCH 136/321] feat!: move mocha options to task options --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/{plugins => tasks}/mocha.ts | 0 plugins/mocha/src/tasks/mocha.ts | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) rename lib/schemas/src/{plugins => tasks}/mocha.ts (100%) diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 7d64b6344..e1a3fee58 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -4,7 +4,6 @@ import { DopplerSchema } from './plugins/doppler' import { RootSchema } from './plugins/dotcom-tool-kit' import { HerokuSchema } from './plugins/heroku' import { LintStagedNpmSchema } from './plugins/lint-staged-npm' -import { MochaSchema } from './plugins/mocha' import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' import { NodeSchema } from './plugins/node' @@ -25,7 +24,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/doppler': DopplerSchema, '@dotcom-tool-kit/heroku': HerokuSchema, '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, - '@dotcom-tool-kit/mocha': MochaSchema, '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, '@dotcom-tool-kit/node': NodeSchema, diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index dbbc6b4de..d03d81858 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -2,11 +2,13 @@ import { type InferSchemaOptions } from './infer' import { BabelSchema } from './tasks/babel' import { ESLintSchema } from './tasks/eslint' import { JestSchema } from './tasks/jest' +import { MochaSchema } from './tasks/mocha' export const TaskSchemas = { Babel: BabelSchema, Eslint: ESLintSchema, - Jest: JestSchema + Jest: JestSchema, + Mocha: MochaSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/mocha.ts b/lib/schemas/src/tasks/mocha.ts similarity index 100% rename from lib/schemas/src/plugins/mocha.ts rename to lib/schemas/src/tasks/mocha.ts diff --git a/plugins/mocha/src/tasks/mocha.ts b/plugins/mocha/src/tasks/mocha.ts index d309c2511..12c4d1ba9 100644 --- a/plugins/mocha/src/tasks/mocha.ts +++ b/plugins/mocha/src/tasks/mocha.ts @@ -1,20 +1,20 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' import { glob } from 'glob' -import { MochaSchema } from '@dotcom-tool-kit/schemas/lib/plugins/mocha' +import { MochaSchema } from '@dotcom-tool-kit/schemas/lib/tasks/mocha' import { fork } from 'child_process' import { promisify } from 'util' const mochaCLIPath = require.resolve('mocha/bin/mocha') -export default class Mocha extends Task<{ plugin: typeof MochaSchema }> { +export default class Mocha extends Task<{ task: typeof MochaSchema }> { static description = '' async run(): Promise { - const files = await promisify(glob)(this.pluginOptions.files) + const files = await promisify(glob)(this.options.files) const args = ['--color', ...files] - if (this.pluginOptions.configPath) { - args.unshift(`--config=${this.pluginOptions.configPath}`) + if (this.options.configPath) { + args.unshift(`--config=${this.options.configPath}`) } this.logger.info(`running mocha ${args.join(' ')}`) const child = fork(mochaCLIPath, args, { silent: true }) From 224543ff65124698b74c74817ffe326b4622c50d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:30:56 +0100 Subject: [PATCH 137/321] chore: remove impossible-to-trigger node task entry option error --- plugins/node/src/tasks/node.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index 4eaa44f55..4a4298b4e 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -28,14 +28,6 @@ export default class Node extends Task<{ plugin: typeof NodeSchema }> { port: ports })) - if (!entry) { - const error = new ToolKitError( - `the ${styles.task('Node')} task requires an ${styles.option('entry')} option` - ) - error.details = `this is the entrypoint for your app, e.g. ${styles.filepath('server/app.js')}` - throw error - } - this.logger.verbose('starting the child node process...') const child = fork(entry, args, { env: { From 38b31467c94a40f009d354ac84eef1866a1e516f Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:35:31 +0100 Subject: [PATCH 138/321] feat!: move node options to task options --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/{plugins => tasks}/node.ts | 0 plugins/node/src/tasks/node.ts | 9 ++++----- 4 files changed, 7 insertions(+), 8 deletions(-) rename lib/schemas/src/{plugins => tasks}/node.ts (100%) diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index e1a3fee58..1c97c08df 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -6,7 +6,6 @@ import { HerokuSchema } from './plugins/heroku' import { LintStagedNpmSchema } from './plugins/lint-staged-npm' import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' -import { NodeSchema } from './plugins/node' import { NodemonSchema } from './plugins/nodemon' import { Pa11ySchema } from './plugins/pa11y' import { PrettierSchema } from './plugins/prettier' @@ -26,7 +25,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, - '@dotcom-tool-kit/node': NodeSchema, '@dotcom-tool-kit/nodemon': NodemonSchema, '@dotcom-tool-kit/pa11y': Pa11ySchema, '@dotcom-tool-kit/prettier': PrettierSchema, diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index d03d81858..8d9280d3e 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -3,12 +3,14 @@ import { BabelSchema } from './tasks/babel' import { ESLintSchema } from './tasks/eslint' import { JestSchema } from './tasks/jest' import { MochaSchema } from './tasks/mocha' +import { NodeSchema } from './tasks/node' export const TaskSchemas = { Babel: BabelSchema, Eslint: ESLintSchema, Jest: JestSchema, - Mocha: MochaSchema + Mocha: MochaSchema, + Node: NodeSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/node.ts b/lib/schemas/src/tasks/node.ts similarity index 100% rename from lib/schemas/src/plugins/node.ts rename to lib/schemas/src/tasks/node.ts diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index 4a4298b4e..bcb759c2d 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -1,18 +1,17 @@ -import { ToolKitError } from '@dotcom-tool-kit/error' -import { hookConsole, hookFork, styles } from '@dotcom-tool-kit/logger' +import { hookConsole, hookFork } from '@dotcom-tool-kit/logger' import { writeState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/base' -import { NodeSchema } from '@dotcom-tool-kit/schemas/lib/plugins/node' +import { NodeSchema } from '@dotcom-tool-kit/schemas/lib/tasks/node' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { fork } from 'child_process' import getPort from 'get-port' import waitPort from 'wait-port' -export default class Node extends Task<{ plugin: typeof NodeSchema }> { +export default class Node extends Task<{ task: typeof NodeSchema }> { static description = '' async run(): Promise { - const { entry, args, useVault, ports } = this.pluginOptions + const { entry, args, useVault, ports } = this.options let vaultEnv = {} From 3cfa0857340778d7ef09f27e1d2f809a35236df9 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:36:18 +0100 Subject: [PATCH 139/321] feat!: rename node useVault option to useDoppler --- lib/schemas/src/tasks/node.ts | 2 +- plugins/node/src/tasks/node.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/schemas/src/tasks/node.ts b/lib/schemas/src/tasks/node.ts index e839c6d06..287e0e52c 100644 --- a/lib/schemas/src/tasks/node.ts +++ b/lib/schemas/src/tasks/node.ts @@ -3,7 +3,7 @@ import { z } from 'zod' export const NodeSchema = z.object({ entry: z.string().default('./server/app.js'), args: z.string().array().optional(), - useVault: z.boolean().default(true), + useDoppler: z.boolean().default(true), ports: z.number().array().default([3001, 3002, 3003]) }) export type NodeOptions = z.infer diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index bcb759c2d..946e6cb1b 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -11,14 +11,14 @@ export default class Node extends Task<{ task: typeof NodeSchema }> { static description = '' async run(): Promise { - const { entry, args, useVault, ports } = this.options + const { entry, args, useDoppler, ports } = this.options - let vaultEnv = {} + let dopplerEnv = {} - if (useVault) { - const vault = new DopplerEnvVars(this.logger, 'dev') + if (useDoppler) { + const doppler = new DopplerEnvVars(this.logger, 'dev') - vaultEnv = await vault.get() + dopplerEnv = await doppler.get() } const port = @@ -30,7 +30,7 @@ export default class Node extends Task<{ task: typeof NodeSchema }> { this.logger.verbose('starting the child node process...') const child = fork(entry, args, { env: { - ...vaultEnv, + ...dopplerEnv, PORT: port.toString(), ...process.env }, From 3cc635c7afe8a63d8b20c634124e4d46dfa9e4ee Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:42:25 +0100 Subject: [PATCH 140/321] feat!: move nodemon options to task options --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/{plugins => tasks}/nodemon.ts | 1 + plugins/nodemon/src/tasks/nodemon.ts | 8 ++++---- 4 files changed, 8 insertions(+), 7 deletions(-) rename lib/schemas/src/{plugins => tasks}/nodemon.ts (99%) diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 1c97c08df..3c7f99ed6 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -6,7 +6,6 @@ import { HerokuSchema } from './plugins/heroku' import { LintStagedNpmSchema } from './plugins/lint-staged-npm' import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' -import { NodemonSchema } from './plugins/nodemon' import { Pa11ySchema } from './plugins/pa11y' import { PrettierSchema } from './plugins/prettier' import { ServerlessSchema } from './plugins/serverless' @@ -25,7 +24,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, - '@dotcom-tool-kit/nodemon': NodemonSchema, '@dotcom-tool-kit/pa11y': Pa11ySchema, '@dotcom-tool-kit/prettier': PrettierSchema, '@dotcom-tool-kit/serverless': ServerlessSchema, diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 8d9280d3e..7f5ea04e8 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -4,13 +4,15 @@ import { ESLintSchema } from './tasks/eslint' import { JestSchema } from './tasks/jest' import { MochaSchema } from './tasks/mocha' import { NodeSchema } from './tasks/node' +import { NodemonSchema } from './tasks/nodemon' export const TaskSchemas = { Babel: BabelSchema, Eslint: ESLintSchema, Jest: JestSchema, Mocha: MochaSchema, - Node: NodeSchema + Node: NodeSchema, + Nodemon: NodemonSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/nodemon.ts b/lib/schemas/src/tasks/nodemon.ts similarity index 99% rename from lib/schemas/src/plugins/nodemon.ts rename to lib/schemas/src/tasks/nodemon.ts index 11a12c945..14ae119ba 100644 --- a/lib/schemas/src/plugins/nodemon.ts +++ b/lib/schemas/src/tasks/nodemon.ts @@ -6,6 +6,7 @@ export const NodemonSchema = z.object({ useVault: z.boolean().default(true), ports: z.number().array().default([3001, 3002, 3003]) }) + export type NodemonOptions = z.infer export const Schema = NodemonSchema diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index c122efb2b..867877d5a 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -1,6 +1,6 @@ import { hookFork } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' -import { NodemonSchema } from '@dotcom-tool-kit/schemas/lib/plugins/nodemon' +import { NodemonSchema } from '@dotcom-tool-kit/schemas/lib/tasks/nodemon' import { writeState } from '@dotcom-tool-kit/state' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import getPort from 'get-port' @@ -8,11 +8,11 @@ import nodemon from 'nodemon' import { Readable } from 'stream' import { shouldDisableNativeFetch } from 'dotcom-tool-kit' -export default class Nodemon extends Task<{ plugin: typeof NodemonSchema }> { +export default class Nodemon extends Task<{ task: typeof NodemonSchema }> { static description = '' async run(): Promise { - const { entry, configPath, useVault, ports } = this.pluginOptions + const { entry, configPath, useVault, ports } = this.options let dopplerEnv = {} @@ -44,7 +44,7 @@ export default class Nodemon extends Task<{ plugin: typeof NodemonSchema }> { nodemon(config) nodemon.on('readable', () => { // These fields aren't specified in the type declaration for some reason - const { stdout, stderr } = (nodemon as unknown) as { stdout: Readable; stderr: Readable } + const { stdout, stderr } = nodemon as unknown as { stdout: Readable; stderr: Readable } hookFork(this.logger, entry, { stdout, stderr }) }) const nodemonLogger = this.logger.child({ process: 'nodemon' }) From 53a051f214620b5109a9ac2d2078298256d4b648 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:43:34 +0100 Subject: [PATCH 141/321] feat!: rename nodemon useVault option to useDoppler --- lib/schemas/src/tasks/nodemon.ts | 2 +- plugins/nodemon/src/tasks/nodemon.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/schemas/src/tasks/nodemon.ts b/lib/schemas/src/tasks/nodemon.ts index 14ae119ba..3f9151fc0 100644 --- a/lib/schemas/src/tasks/nodemon.ts +++ b/lib/schemas/src/tasks/nodemon.ts @@ -3,7 +3,7 @@ import { z } from 'zod' export const NodemonSchema = z.object({ entry: z.string().default('./server/app.js'), configPath: z.string().optional(), - useVault: z.boolean().default(true), + useDoppler: z.boolean().default(true), ports: z.number().array().default([3001, 3002, 3003]) }) diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index 867877d5a..3dbfb2f78 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -12,11 +12,11 @@ export default class Nodemon extends Task<{ task: typeof NodemonSchema }> { static description = '' async run(): Promise { - const { entry, configPath, useVault, ports } = this.options + const { entry, configPath, useDoppler, ports } = this.options let dopplerEnv = {} - if (useVault) { + if (useDoppler) { const doppler = new DopplerEnvVars(this.logger, 'dev') dopplerEnv = await doppler.get() From d6ac04ce71eece7e0ee138cab75087c9f980c49a Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:49:03 +0100 Subject: [PATCH 142/321] feat!: move pa11y options to task options --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/{plugins => tasks}/pa11y.ts | 1 + plugins/pa11y/src/tasks/pa11y.ts | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) rename lib/schemas/src/{plugins => tasks}/pa11y.ts (99%) diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 3c7f99ed6..55b2fe373 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -6,7 +6,6 @@ import { HerokuSchema } from './plugins/heroku' import { LintStagedNpmSchema } from './plugins/lint-staged-npm' import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' -import { Pa11ySchema } from './plugins/pa11y' import { PrettierSchema } from './plugins/prettier' import { ServerlessSchema } from './plugins/serverless' import { TypeScriptSchema } from './plugins/typescript' @@ -24,7 +23,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, - '@dotcom-tool-kit/pa11y': Pa11ySchema, '@dotcom-tool-kit/prettier': PrettierSchema, '@dotcom-tool-kit/serverless': ServerlessSchema, '@dotcom-tool-kit/typescript': TypeScriptSchema, diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 7f5ea04e8..86c2e976e 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -5,6 +5,7 @@ import { JestSchema } from './tasks/jest' import { MochaSchema } from './tasks/mocha' import { NodeSchema } from './tasks/node' import { NodemonSchema } from './tasks/nodemon' +import { Pa11ySchema } from './tasks/pa11y' export const TaskSchemas = { Babel: BabelSchema, @@ -12,7 +13,8 @@ export const TaskSchemas = { Jest: JestSchema, Mocha: MochaSchema, Node: NodeSchema, - Nodemon: NodemonSchema + Nodemon: NodemonSchema, + Pa11y: Pa11ySchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/pa11y.ts b/lib/schemas/src/tasks/pa11y.ts similarity index 99% rename from lib/schemas/src/plugins/pa11y.ts rename to lib/schemas/src/tasks/pa11y.ts index cd0e64039..704580ac2 100644 --- a/lib/schemas/src/plugins/pa11y.ts +++ b/lib/schemas/src/tasks/pa11y.ts @@ -3,6 +3,7 @@ import { z } from 'zod' export const Pa11ySchema = z.object({ configFile: z.string().optional() }) + export type Pa11yOptions = z.infer export const Schema = Pa11ySchema diff --git a/plugins/pa11y/src/tasks/pa11y.ts b/plugins/pa11y/src/tasks/pa11y.ts index fa6febb85..536c33cf7 100644 --- a/plugins/pa11y/src/tasks/pa11y.ts +++ b/plugins/pa11y/src/tasks/pa11y.ts @@ -1,12 +1,12 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' -import type { Pa11ySchema } from '@dotcom-tool-kit/schemas/lib/plugins/pa11y' +import type { Pa11ySchema } from '@dotcom-tool-kit/schemas/lib/tasks/pa11y' import { fork } from 'child_process' import { readState } from '@dotcom-tool-kit/state' const pa11yCIPath = require.resolve('pa11y-ci/bin/pa11y-ci') -export default class Pa11y extends Task<{ plugin: typeof Pa11ySchema }> { +export default class Pa11y extends Task<{ task: typeof Pa11ySchema }> { static description = '' async run(): Promise { @@ -19,7 +19,7 @@ export default class Pa11y extends Task<{ plugin: typeof Pa11ySchema }> { process.env.TEST_URL = `https://${reviewState.appName}.herokuapp.com` } - const args = this.pluginOptions.configFile ? ['--config', this.pluginOptions.configFile] : [] + const args = this.options.configFile ? ['--config', this.options.configFile] : [] this.logger.info(`running pa11y-ci ${args.join(' ')}`) const child = fork(pa11yCIPath, args, { silent: true }) From 945aa82a8aad8b622683eb8f07e5dc8180e93c5a Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:51:00 +0100 Subject: [PATCH 143/321] feat!: move prettier options to task options --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/{plugins => tasks}/prettier.ts | 1 + plugins/prettier/src/tasks/prettier.ts | 10 +++++----- 4 files changed, 9 insertions(+), 8 deletions(-) rename lib/schemas/src/{plugins => tasks}/prettier.ts (99%) diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 55b2fe373..b03387f24 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -6,7 +6,6 @@ import { HerokuSchema } from './plugins/heroku' import { LintStagedNpmSchema } from './plugins/lint-staged-npm' import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' -import { PrettierSchema } from './plugins/prettier' import { ServerlessSchema } from './plugins/serverless' import { TypeScriptSchema } from './plugins/typescript' import { UploadAssetsToS3Schema } from './plugins/upload-assets-to-s3' @@ -23,7 +22,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, - '@dotcom-tool-kit/prettier': PrettierSchema, '@dotcom-tool-kit/serverless': ServerlessSchema, '@dotcom-tool-kit/typescript': TypeScriptSchema, '@dotcom-tool-kit/upload-assets-to-s3': UploadAssetsToS3Schema, diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 86c2e976e..ea6f56d5d 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -6,6 +6,7 @@ import { MochaSchema } from './tasks/mocha' import { NodeSchema } from './tasks/node' import { NodemonSchema } from './tasks/nodemon' import { Pa11ySchema } from './tasks/pa11y' +import { PrettierSchema } from './tasks/prettier' export const TaskSchemas = { Babel: BabelSchema, @@ -14,7 +15,8 @@ export const TaskSchemas = { Mocha: MochaSchema, Node: NodeSchema, Nodemon: NodemonSchema, - Pa11y: Pa11ySchema + Pa11y: Pa11ySchema, + Prettier: PrettierSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/prettier.ts b/lib/schemas/src/tasks/prettier.ts similarity index 99% rename from lib/schemas/src/plugins/prettier.ts rename to lib/schemas/src/tasks/prettier.ts index 98dc5417e..653476743 100644 --- a/lib/schemas/src/plugins/prettier.ts +++ b/lib/schemas/src/tasks/prettier.ts @@ -12,6 +12,7 @@ export const PrettierSchema = z.object({ trailingComma: 'none' }) }) + export type PrettierOptions = z.infer export const Schema = PrettierSchema diff --git a/plugins/prettier/src/tasks/prettier.ts b/plugins/prettier/src/tasks/prettier.ts index eccc78ac5..1a0731f3c 100644 --- a/plugins/prettier/src/tasks/prettier.ts +++ b/plugins/prettier/src/tasks/prettier.ts @@ -1,21 +1,21 @@ import prettier from 'prettier' -import { PrettierOptions, PrettierSchema } from '@dotcom-tool-kit/schemas/lib/plugins/prettier' +import { PrettierOptions, PrettierSchema } from '@dotcom-tool-kit/schemas/lib/tasks/prettier' import { promises as fsp } from 'fs' import fg from 'fast-glob' import { hookConsole, styles } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' import { ToolKitError } from '@dotcom-tool-kit/error' -export default class Prettier extends Task<{ plugin: typeof PrettierSchema }> { +export default class Prettier extends Task<{ task: typeof PrettierSchema }> { static description = '' async run(files?: string[]): Promise { try { - const filepaths = await fg(files ?? this.pluginOptions.files) + const filepaths = await fg(files ?? this.options.files) for (const filepath of filepaths) { const { ignored } = await prettier.getFileInfo(filepath) if (!ignored) { - await this.formatFile(filepath, this.pluginOptions) + await this.formatFile(filepath, this.options) } } } catch (err) { @@ -50,7 +50,7 @@ export default class Prettier extends Task<{ plugin: typeof PrettierSchema }> { prettierConfig = options.configOptions } - const { ignored } = await prettier.getFileInfo(filepath, { ignorePath: this.pluginOptions.ignoreFile }) + const { ignored } = await prettier.getFileInfo(filepath, { ignorePath: this.options.ignoreFile }) if (ignored) { return From 06f358e71f8d62ae58fe05527621ac001dcdff4b Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 15:53:32 +0100 Subject: [PATCH 144/321] feat!: remove prettier configOptions option we don't do that here --- lib/schemas/src/tasks/prettier.ts | 9 +-------- plugins/prettier/src/tasks/prettier.ts | 13 +------------ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/lib/schemas/src/tasks/prettier.ts b/lib/schemas/src/tasks/prettier.ts index 653476743..75f0b03c3 100644 --- a/lib/schemas/src/tasks/prettier.ts +++ b/lib/schemas/src/tasks/prettier.ts @@ -3,14 +3,7 @@ import { z } from 'zod' export const PrettierSchema = z.object({ files: z.string().array().or(z.string()).default(['**/*.{js,jsx,ts,tsx}']), configFile: z.string().optional(), - ignoreFile: z.string().default('.prettierignore'), - configOptions: z.record(z.unknown()).default({ - singleQuote: true, - useTabs: true, - bracketSpacing: true, - arrowParens: 'always', - trailingComma: 'none' - }) + ignoreFile: z.string().default('.prettierignore') }) export type PrettierOptions = z.infer diff --git a/plugins/prettier/src/tasks/prettier.ts b/plugins/prettier/src/tasks/prettier.ts index 1a0731f3c..fa8953222 100644 --- a/plugins/prettier/src/tasks/prettier.ts +++ b/plugins/prettier/src/tasks/prettier.ts @@ -41,14 +41,6 @@ export default class Prettier extends Task<{ task: typeof PrettierSchema }> { throw error } } - if (!prettierConfig && options.configOptions) { - this.logger.warn( - `prettier could not find the specified configFile${ - options.configFile ? ` (${styles.filepath(options.configFile)})` : '' - }), using ${styles.option('configOptions')} instead` - ) - prettierConfig = options.configOptions - } const { ignored } = await prettier.getFileInfo(filepath, { ignorePath: this.options.ignoreFile }) @@ -58,10 +50,7 @@ export default class Prettier extends Task<{ task: typeof PrettierSchema }> { const unhook = hookConsole(this.logger, 'prettier') try { - await fsp.writeFile( - filepath, - prettier.format(fileContent, { ...(prettierConfig as prettier.Options), filepath }) - ) + await fsp.writeFile(filepath, prettier.format(fileContent, { ...prettierConfig, filepath })) } finally { unhook() } From 55f8c4caf23cb09d874eb0968172058b7d899228 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 16:00:55 +0100 Subject: [PATCH 145/321] feat!: consolidate typescript tasks and move options to task options --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- .../src/{plugins => tasks}/typescript.ts | 1 + plugins/typescript/.toolkitrc.yml | 15 +++++++-------- plugins/typescript/src/tasks/build.ts | 7 ------- plugins/typescript/src/tasks/test.ts | 7 ------- plugins/typescript/src/tasks/typescript.ts | 18 +++++++++--------- plugins/typescript/src/tasks/watch.ts | 7 ------- 8 files changed, 20 insertions(+), 41 deletions(-) rename lib/schemas/src/{plugins => tasks}/typescript.ts (99%) delete mode 100644 plugins/typescript/src/tasks/build.ts delete mode 100644 plugins/typescript/src/tasks/test.ts delete mode 100644 plugins/typescript/src/tasks/watch.ts diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index b03387f24..70503cca6 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -7,7 +7,6 @@ import { LintStagedNpmSchema } from './plugins/lint-staged-npm' import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' import { ServerlessSchema } from './plugins/serverless' -import { TypeScriptSchema } from './plugins/typescript' import { UploadAssetsToS3Schema } from './plugins/upload-assets-to-s3' import { VaultSchema } from './plugins/vault' import { WebpackSchema } from './plugins/webpack' @@ -23,7 +22,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, '@dotcom-tool-kit/serverless': ServerlessSchema, - '@dotcom-tool-kit/typescript': TypeScriptSchema, '@dotcom-tool-kit/upload-assets-to-s3': UploadAssetsToS3Schema, '@dotcom-tool-kit/vault': VaultSchema, '@dotcom-tool-kit/webpack': WebpackSchema diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index ea6f56d5d..75e77e8e2 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -7,6 +7,7 @@ import { NodeSchema } from './tasks/node' import { NodemonSchema } from './tasks/nodemon' import { Pa11ySchema } from './tasks/pa11y' import { PrettierSchema } from './tasks/prettier' +import { TypeScriptSchema } from './tasks/typescript' export const TaskSchemas = { Babel: BabelSchema, @@ -16,7 +17,8 @@ export const TaskSchemas = { Node: NodeSchema, Nodemon: NodemonSchema, Pa11y: Pa11ySchema, - Prettier: PrettierSchema + Prettier: PrettierSchema, + TypeScript: TypeScriptSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/typescript.ts b/lib/schemas/src/tasks/typescript.ts similarity index 99% rename from lib/schemas/src/plugins/typescript.ts rename to lib/schemas/src/tasks/typescript.ts index 5427e7005..709d25643 100644 --- a/lib/schemas/src/plugins/typescript.ts +++ b/lib/schemas/src/tasks/typescript.ts @@ -4,6 +4,7 @@ export const TypeScriptSchema = z.object({ configPath: z.string().optional(), extraArgs: z.string().array().optional() }) + export type TypeScriptOptions = z.infer export const Schema = TypeScriptSchema diff --git a/plugins/typescript/.toolkitrc.yml b/plugins/typescript/.toolkitrc.yml index 20f945b9a..9523ef286 100644 --- a/plugins/typescript/.toolkitrc.yml +++ b/plugins/typescript/.toolkitrc.yml @@ -1,13 +1,12 @@ tasks: - TypeScriptBuild: './lib/tasks/build' - TypeScriptWatch: './lib/tasks/watch' - TypeScriptTest: './lib/tasks/test' + TypeScript: './lib/tasks' commands: - 'build:local': TypeScriptBuild - 'build:ci': TypeScriptBuild - 'build:remote': TypeScriptBuild - 'run:local': TypeScriptWatch - 'test:local': TypeScriptTest + # TODO add options here once we support per-command-assignment options + 'build:local': TypeScript + 'build:ci': TypeScript + 'build:remote': TypeScript + 'run:local': TypeScript # watch + 'test:local': TypeScript # noEmit version: 2 diff --git a/plugins/typescript/src/tasks/build.ts b/plugins/typescript/src/tasks/build.ts deleted file mode 100644 index ce9610b25..000000000 --- a/plugins/typescript/src/tasks/build.ts +++ /dev/null @@ -1,7 +0,0 @@ -import TypeScriptTask from './typescript' - -export default class TypeScriptBuild extends TypeScriptTask { - static description = 'compile TypeScript to JavaScript' - - taskArgs = [] -} diff --git a/plugins/typescript/src/tasks/test.ts b/plugins/typescript/src/tasks/test.ts deleted file mode 100644 index f333c6ae6..000000000 --- a/plugins/typescript/src/tasks/test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import TypeScriptTask from './typescript' - -export default class TypeScriptTest extends TypeScriptTask { - static description = 'type check TypeScript code' - - taskArgs = ['--noEmit'] -} diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index 9b61db94c..7051e9bd3 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -1,21 +1,21 @@ import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' -import type { TypeScriptSchema } from '@dotcom-tool-kit/schemas/lib/plugins/typescript' +import type { TypeScriptSchema } from '@dotcom-tool-kit/schemas/lib/tasks/typescript' import { fork } from 'child_process' const tscPath = require.resolve('typescript/bin/tsc') -export default abstract class TypeScriptTask extends Task<{ plugin: typeof TypeScriptSchema }> { - abstract taskArgs: string[] - +export default class TypeScript extends Task<{ task: typeof TypeScriptSchema }> { async run(): Promise { // TODO: add monorepo support with --build option - const args = [...this.taskArgs] - if (this.pluginOptions.configPath) { - args.unshift('--project', this.pluginOptions.configPath) + const args = [] + + if (this.options.configPath) { + args.unshift('--project', this.options.configPath) } - if (this.pluginOptions.extraArgs) { - args.push(...this.pluginOptions.extraArgs) + + if (this.options.extraArgs) { + args.push(...this.options.extraArgs) } const child = fork(tscPath, args, { silent: true }) diff --git a/plugins/typescript/src/tasks/watch.ts b/plugins/typescript/src/tasks/watch.ts deleted file mode 100644 index 43e79161b..000000000 --- a/plugins/typescript/src/tasks/watch.ts +++ /dev/null @@ -1,7 +0,0 @@ -import TypeScriptTask from './typescript' - -export default class TypeScriptWatch extends TypeScriptTask { - static description = 'rebuild TypeScript project every file change' - - taskArgs = ['--watch'] -} From 426d82f6ef3b600ec416448470ab46cb90058afe Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 16:02:34 +0100 Subject: [PATCH 146/321] feat!: remove typescript extraArgs option --- lib/schemas/src/tasks/typescript.ts | 3 +-- plugins/typescript/src/tasks/typescript.ts | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/schemas/src/tasks/typescript.ts b/lib/schemas/src/tasks/typescript.ts index 709d25643..af2868d38 100644 --- a/lib/schemas/src/tasks/typescript.ts +++ b/lib/schemas/src/tasks/typescript.ts @@ -1,8 +1,7 @@ import { z } from 'zod' export const TypeScriptSchema = z.object({ - configPath: z.string().optional(), - extraArgs: z.string().array().optional() + configPath: z.string().optional() }) export type TypeScriptOptions = z.infer diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index 7051e9bd3..048d4ab7b 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -14,10 +14,6 @@ export default class TypeScript extends Task<{ task: typeof TypeScriptSchema }> args.unshift('--project', this.options.configPath) } - if (this.options.extraArgs) { - args.push(...this.options.extraArgs) - } - const child = fork(tscPath, args, { silent: true }) hookFork(this.logger, 'typescript', child) const exitPromise = waitOnExit('typescript', child) From d73332579afedec9c3027c09ab1efd6f1e58d73c Mon Sep 17 00:00:00 2001 From: cerdfied Date: Mon, 8 Apr 2024 16:38:50 +0100 Subject: [PATCH 147/321] feat!: move upload-assets-to-s3 options to task options --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/{plugins => tasks}/upload-assets-to-s3.ts | 0 package-lock.json | 5 ++++- .../upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts | 6 +++--- 5 files changed, 10 insertions(+), 7 deletions(-) rename lib/schemas/src/{plugins => tasks}/upload-assets-to-s3.ts (100%) diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 70503cca6..9eb256257 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -7,7 +7,6 @@ import { LintStagedNpmSchema } from './plugins/lint-staged-npm' import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' import { ServerlessSchema } from './plugins/serverless' -import { UploadAssetsToS3Schema } from './plugins/upload-assets-to-s3' import { VaultSchema } from './plugins/vault' import { WebpackSchema } from './plugins/webpack' import { type InferSchemaOptions } from './infer' @@ -22,7 +21,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, '@dotcom-tool-kit/serverless': ServerlessSchema, - '@dotcom-tool-kit/upload-assets-to-s3': UploadAssetsToS3Schema, '@dotcom-tool-kit/vault': VaultSchema, '@dotcom-tool-kit/webpack': WebpackSchema } diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 75e77e8e2..60e486740 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -8,6 +8,7 @@ import { NodemonSchema } from './tasks/nodemon' import { Pa11ySchema } from './tasks/pa11y' import { PrettierSchema } from './tasks/prettier' import { TypeScriptSchema } from './tasks/typescript' +import { UploadAssetsToS3Schema } from './tasks/upload-assets-to-s3' export const TaskSchemas = { Babel: BabelSchema, @@ -18,7 +19,8 @@ export const TaskSchemas = { Nodemon: NodemonSchema, Pa11y: Pa11ySchema, Prettier: PrettierSchema, - TypeScript: TypeScriptSchema + TypeScript: TypeScriptSchema, + UploadAssetsToS3: UploadAssetsToS3Schema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/upload-assets-to-s3.ts b/lib/schemas/src/tasks/upload-assets-to-s3.ts similarity index 100% rename from lib/schemas/src/plugins/upload-assets-to-s3.ts rename to lib/schemas/src/tasks/upload-assets-to-s3.ts diff --git a/package-lock.json b/package-lock.json index 5c6ec9d46..09abf90b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1092,7 +1092,6 @@ "core/sandbox": { "name": "@financial-times/sandbox", "version": "1.0.0", - "extraneous": true, "license": "ISC", "dependencies": { "@dotcom-tool-kit/base": "file:../../lib/base", @@ -6638,6 +6637,10 @@ "version": "3.0.0", "license": "MIT" }, + "node_modules/@financial-times/sandbox": { + "resolved": "core/sandbox", + "link": true + }, "node_modules/@gar/promisify": { "version": "1.1.3", "license": "MIT" diff --git a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts index e9e297f13..a2fad5d4d 100644 --- a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts +++ b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts @@ -9,13 +9,13 @@ import { styles } from '@dotcom-tool-kit/logger' import { UploadAssetsToS3Options, UploadAssetsToS3Schema -} from '@dotcom-tool-kit/schemas/lib/plugins/upload-assets-to-s3' +} from '@dotcom-tool-kit/schemas/lib/tasks/upload-assets-to-s3' -export default class UploadAssetsToS3 extends Task<{ plugin: typeof UploadAssetsToS3Schema }> { +export default class UploadAssetsToS3 extends Task<{ task: typeof UploadAssetsToS3Schema }> { static description = '' async run(): Promise { - await this.uploadAssetsToS3(this.pluginOptions) + await this.uploadAssetsToS3(this.options) } async uploadFile(file: string, options: UploadAssetsToS3Options, s3: S3Client): Promise { const type = getFileType(file) From 9f85554362cbbf4c2207e61165cf5d0ae1e0dc01 Mon Sep 17 00:00:00 2001 From: cerdfied Date: Mon, 8 Apr 2024 17:10:40 +0100 Subject: [PATCH 148/321] feat!: move webpack options to task options and allow configuring env --- lib/schemas/src/plugins.ts | 4 +- lib/schemas/src/tasks.ts | 4 +- lib/schemas/src/{plugins => tasks}/webpack.ts | 4 +- plugins/webpack/.toolkitrc.yml | 12 +++--- plugins/webpack/src/run-webpack.ts | 38 ------------------- plugins/webpack/src/tasks/development.ts | 14 ------- plugins/webpack/src/tasks/production.ts | 14 ------- plugins/webpack/src/tasks/watch.ts | 16 -------- plugins/webpack/src/tasks/webpack.ts | 34 +++++++++++++++++ 9 files changed, 46 insertions(+), 94 deletions(-) rename lib/schemas/src/{plugins => tasks}/webpack.ts (53%) delete mode 100644 plugins/webpack/src/run-webpack.ts delete mode 100644 plugins/webpack/src/tasks/development.ts delete mode 100644 plugins/webpack/src/tasks/production.ts delete mode 100644 plugins/webpack/src/tasks/watch.ts create mode 100644 plugins/webpack/src/tasks/webpack.ts diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index 9eb256257..fe3bae95e 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -8,7 +8,6 @@ import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' import { ServerlessSchema } from './plugins/serverless' import { VaultSchema } from './plugins/vault' -import { WebpackSchema } from './plugins/webpack' import { type InferSchemaOptions } from './infer' export const PluginSchemas = { @@ -21,8 +20,7 @@ export const PluginSchemas = { '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, '@dotcom-tool-kit/serverless': ServerlessSchema, - '@dotcom-tool-kit/vault': VaultSchema, - '@dotcom-tool-kit/webpack': WebpackSchema + '@dotcom-tool-kit/vault': VaultSchema } export type PluginOptions = InferSchemaOptions diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 60e486740..e16df2555 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -9,6 +9,7 @@ import { Pa11ySchema } from './tasks/pa11y' import { PrettierSchema } from './tasks/prettier' import { TypeScriptSchema } from './tasks/typescript' import { UploadAssetsToS3Schema } from './tasks/upload-assets-to-s3' +import { WebpackSchema } from './tasks/webpack' export const TaskSchemas = { Babel: BabelSchema, @@ -20,7 +21,8 @@ export const TaskSchemas = { Pa11y: Pa11ySchema, Prettier: PrettierSchema, TypeScript: TypeScriptSchema, - UploadAssetsToS3: UploadAssetsToS3Schema + UploadAssetsToS3: UploadAssetsToS3Schema, + Webpack: WebpackSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/webpack.ts b/lib/schemas/src/tasks/webpack.ts similarity index 53% rename from lib/schemas/src/plugins/webpack.ts rename to lib/schemas/src/tasks/webpack.ts index d14c5ad13..ab93af618 100644 --- a/lib/schemas/src/plugins/webpack.ts +++ b/lib/schemas/src/tasks/webpack.ts @@ -1,7 +1,9 @@ import { z } from 'zod' export const WebpackSchema = z.object({ - configPath: z.string().optional() + configPath: z.string().optional(), + envName: z.union([z.literal('production'), z.literal('development')]), + watch: z.boolean().optional() }) export type WebpackOptions = z.infer diff --git a/plugins/webpack/.toolkitrc.yml b/plugins/webpack/.toolkitrc.yml index 7bf7de328..1a16c57e5 100644 --- a/plugins/webpack/.toolkitrc.yml +++ b/plugins/webpack/.toolkitrc.yml @@ -1,12 +1,10 @@ tasks: - WebpackDevelopment: './lib/tasks/development' - WebpackProduction: './lib/tasks/production' - WebpackWatch: './lib/tasks/watch' + Webpack: './lib/tasks/webpack' commands: - 'build:local': WebpackDevelopment - 'build:ci': WebpackProduction - 'build:remote': WebpackProduction - 'run:local': WebpackWatch + 'build:local': Webpack + 'build:ci': Webpack + 'build:remote': Webpack + 'run:local': Webpack version: 2 diff --git a/plugins/webpack/src/run-webpack.ts b/plugins/webpack/src/run-webpack.ts deleted file mode 100644 index 0f0b82f1b..000000000 --- a/plugins/webpack/src/run-webpack.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { fork } from 'child_process' -import { Logger } from 'winston' -import type { WebpackOptions } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' -import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' - -const webpackCLIPath = require.resolve('webpack-cli/bin/cli') - -export interface RunWebpackOptions { - mode: 'production' | 'development' - watch?: boolean -} - -export default function runWebpack( - logger: Logger, - options: WebpackOptions & RunWebpackOptions -): Promise { - logger.info('starting Webpack...') - const args = ['build', '--color', `--mode=${options.mode}`] - - if (options.configPath) { - args.push(`--config=${options.configPath}`) - } - - if (options.watch) { - args.push('--watch') - } - - let { execArgv } = process - if (process.allowedNodeEnvironmentFlags.has('--openssl-legacy-provider')) { - // webpack 4 uses a legacy hashing function that is no longer provided by - // default in OpenSSL 3: https://github.com/webpack/webpack/issues/14532 - execArgv = [...execArgv, '--openssl-legacy-provider'] - } - - const child = fork(webpackCLIPath, args, { silent: true, execArgv }) - hookFork(logger, 'webpack', child) - return waitOnExit('webpack', child) -} diff --git a/plugins/webpack/src/tasks/development.ts b/plugins/webpack/src/tasks/development.ts deleted file mode 100644 index 5b1de06a1..000000000 --- a/plugins/webpack/src/tasks/development.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Task } from '@dotcom-tool-kit/base' -import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' -import runWebpack from '../run-webpack' - -export default class WebpackDevelopment extends Task<{ plugin: typeof WebpackSchema }> { - static description = 'Run Webpack in development mode' - - async run(): Promise { - await runWebpack(this.logger, { - ...this.pluginOptions, - mode: 'development' - }) - } -} diff --git a/plugins/webpack/src/tasks/production.ts b/plugins/webpack/src/tasks/production.ts deleted file mode 100644 index 57fe1a9a9..000000000 --- a/plugins/webpack/src/tasks/production.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Task } from '@dotcom-tool-kit/base' -import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' -import runWebpack from '../run-webpack' - -export default class WebpackProduction extends Task<{ plugin: typeof WebpackSchema }> { - static description = 'Run Webpack in production mode' - - async run(): Promise { - await runWebpack(this.logger, { - ...this.pluginOptions, - mode: 'production' - }) - } -} diff --git a/plugins/webpack/src/tasks/watch.ts b/plugins/webpack/src/tasks/watch.ts deleted file mode 100644 index c0b521ed2..000000000 --- a/plugins/webpack/src/tasks/watch.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Task } from '@dotcom-tool-kit/base' -import { WebpackSchema } from '@dotcom-tool-kit/schemas/lib/plugins/webpack' -import runWebpack from '../run-webpack' - -export default class WebpackWatch extends Task<{ plugin: typeof WebpackSchema }> { - static description = 'Run Webpack in watch mode in the background' - - async run(): Promise { - // don't wait for Webpack to exit, to leave it running in the background - runWebpack(this.logger, { - ...this.pluginOptions, - mode: 'development', - watch: true - }) - } -} diff --git a/plugins/webpack/src/tasks/webpack.ts b/plugins/webpack/src/tasks/webpack.ts new file mode 100644 index 000000000..f0665a8d1 --- /dev/null +++ b/plugins/webpack/src/tasks/webpack.ts @@ -0,0 +1,34 @@ +import { type WebpackSchema } from '@dotcom-tool-kit/schemas/lib/tasks/webpack' +import { Task } from '@dotcom-tool-kit/base' +import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' +import { fork } from 'child_process' + +const webpackCLIPath = require.resolve('webpack-cli/bin/cli') + +export default class Babel extends Task<{ task: typeof WebpackSchema }> { + static description = 'build babel' + + async run(): Promise { + this.logger.info('starting Webpack...') + const args = ['build', '--color', `--mode=${this.options.envName}`] + + if (this.options.configPath) { + args.push(`--config=${this.options.configPath}`) + } + + if (this.options.watch) { + args.push('--watch') + } + + let { execArgv } = process + if (process.allowedNodeEnvironmentFlags.has('--openssl-legacy-provider')) { + // webpack 4 uses a legacy hashing function that is no longer provided by + // default in OpenSSL 3: https://github.com/webpack/webpack/issues/14532 + execArgv = [...execArgv, '--openssl-legacy-provider'] + } + + const child = fork(webpackCLIPath, args, { silent: true, execArgv }) + hookFork(this.logger, 'webpack', child) + return waitOnExit('webpack', child) + } +} From c74af9b4394493f52287c38d0b0402c9b3f61cc6 Mon Sep 17 00:00:00 2001 From: cerdfied Date: Mon, 8 Apr 2024 17:17:33 +0100 Subject: [PATCH 149/321] feat!: move n-test options to task options --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/{plugins => tasks}/n-test.ts | 0 plugins/n-test/src/tasks/n-test.ts | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) rename lib/schemas/src/{plugins => tasks}/n-test.ts (100%) diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index fe3bae95e..aab232075 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -4,7 +4,6 @@ import { DopplerSchema } from './plugins/doppler' import { RootSchema } from './plugins/dotcom-tool-kit' import { HerokuSchema } from './plugins/heroku' import { LintStagedNpmSchema } from './plugins/lint-staged-npm' -import { SmokeTestSchema } from './plugins/n-test' import { NextRouterSchema } from './plugins/next-router' import { ServerlessSchema } from './plugins/serverless' import { VaultSchema } from './plugins/vault' @@ -17,7 +16,6 @@ export const PluginSchemas = { '@dotcom-tool-kit/doppler': DopplerSchema, '@dotcom-tool-kit/heroku': HerokuSchema, '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, - '@dotcom-tool-kit/n-test': SmokeTestSchema, '@dotcom-tool-kit/next-router': NextRouterSchema, '@dotcom-tool-kit/serverless': ServerlessSchema, '@dotcom-tool-kit/vault': VaultSchema diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index e16df2555..c89dd5bb5 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -10,6 +10,7 @@ import { PrettierSchema } from './tasks/prettier' import { TypeScriptSchema } from './tasks/typescript' import { UploadAssetsToS3Schema } from './tasks/upload-assets-to-s3' import { WebpackSchema } from './tasks/webpack' +import { SmokeTestSchema } from './tasks/n-test' export const TaskSchemas = { Babel: BabelSchema, @@ -22,7 +23,8 @@ export const TaskSchemas = { Prettier: PrettierSchema, TypeScript: TypeScriptSchema, UploadAssetsToS3: UploadAssetsToS3Schema, - Webpack: WebpackSchema + Webpack: WebpackSchema, + NTest: SmokeTestSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/n-test.ts b/lib/schemas/src/tasks/n-test.ts similarity index 100% rename from lib/schemas/src/plugins/n-test.ts rename to lib/schemas/src/tasks/n-test.ts diff --git a/plugins/n-test/src/tasks/n-test.ts b/plugins/n-test/src/tasks/n-test.ts index e51f830be..ee020b295 100644 --- a/plugins/n-test/src/tasks/n-test.ts +++ b/plugins/n-test/src/tasks/n-test.ts @@ -1,10 +1,10 @@ import { styles } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' -import { SmokeTestSchema } from '@dotcom-tool-kit/schemas/lib/plugins/n-test' +import { SmokeTestSchema } from '@dotcom-tool-kit/schemas/lib/tasks/n-test' import { SmokeTest } from '@financial-times/n-test' import { readState } from '@dotcom-tool-kit/state' -export default class NTest extends Task<{ plugin: typeof SmokeTestSchema }> { +export default class NTest extends Task<{ task: typeof SmokeTestSchema }> { static description = '' async run(): Promise { @@ -14,18 +14,18 @@ export default class NTest extends Task<{ plugin: typeof SmokeTestSchema }> { if (appState) { // HACK:20231003:IM keep the old logic of using the app name as the // subdomain to maintain backwards compatibility - this.pluginOptions.host = + this.options.host = 'url' in appState && appState.url ? appState.url : `https://${appState.appName}.herokuapp.com` // HACK:20231003:IM n-test naively appends paths to the host URL so // expects there to be no trailing slash - if (this.pluginOptions.host.endsWith('/')) { - this.pluginOptions.host = this.pluginOptions.host.slice(0, -1) + if (this.options.host.endsWith('/')) { + this.options.host = this.options.host.slice(0, -1) } } - const smokeTest = new SmokeTest(this.pluginOptions) + const smokeTest = new SmokeTest(this.options) this.logger.info( - `Running smoke test${this.pluginOptions.host ? ` for URL ${styles.URL(this.pluginOptions.host)}` : ''}` + `Running smoke test${this.options.host ? ` for URL ${styles.URL(this.options.host)}` : ''}` ) await smokeTest.run() } From 8d65afd3bc46be5624b964b784e5b719608d5094 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 17:11:26 +0100 Subject: [PATCH 150/321] refactor: remove redundant url key check for n-test appState.url --- plugins/n-test/src/tasks/n-test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/n-test/src/tasks/n-test.ts b/plugins/n-test/src/tasks/n-test.ts index ee020b295..5235390dc 100644 --- a/plugins/n-test/src/tasks/n-test.ts +++ b/plugins/n-test/src/tasks/n-test.ts @@ -14,8 +14,7 @@ export default class NTest extends Task<{ task: typeof SmokeTestSchema }> { if (appState) { // HACK:20231003:IM keep the old logic of using the app name as the // subdomain to maintain backwards compatibility - this.options.host = - 'url' in appState && appState.url ? appState.url : `https://${appState.appName}.herokuapp.com` + this.options.host = appState.url ? appState.url : `https://${appState.appName}.herokuapp.com` // HACK:20231003:IM n-test naively appends paths to the host URL so // expects there to be no trailing slash if (this.options.host.endsWith('/')) { From 8be42de121c8c2000a7880e2c22db3cadf96e2aa Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 17:58:06 +0100 Subject: [PATCH 151/321] feat!: consolidate cypress tasks using similar logic to n-test for urls --- plugins/cypress/.toolkitrc.yml | 9 +++---- plugins/cypress/src/tasks/ci.ts | 23 ----------------- plugins/cypress/src/tasks/cypress.ts | 37 ++++++++++++++++++++++++++++ plugins/cypress/src/tasks/local.ts | 24 ------------------ 4 files changed, 41 insertions(+), 52 deletions(-) delete mode 100644 plugins/cypress/src/tasks/ci.ts create mode 100644 plugins/cypress/src/tasks/cypress.ts delete mode 100644 plugins/cypress/src/tasks/local.ts diff --git a/plugins/cypress/.toolkitrc.yml b/plugins/cypress/.toolkitrc.yml index dc8e7c03b..b7154cfae 100644 --- a/plugins/cypress/.toolkitrc.yml +++ b/plugins/cypress/.toolkitrc.yml @@ -1,10 +1,9 @@ tasks: - CypressCi: './lib/tasks/ci' - CypressLocal: './lib/tasks/local' + Cypress: './lib/tasks/cypress' commands: - 'test:review': CypressCi - 'test:staging': CypressCi - 'e2e:local': CypressLocal + 'test:review': Cypress + 'test:staging': Cypress + 'e2e:local': Cypress version: 2 diff --git a/plugins/cypress/src/tasks/ci.ts b/plugins/cypress/src/tasks/ci.ts deleted file mode 100644 index 5737ec552..000000000 --- a/plugins/cypress/src/tasks/ci.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { spawn } from 'child_process' -import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' -import { readState } from '@dotcom-tool-kit/state' -import { Task } from '@dotcom-tool-kit/base' -import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' - -export default class CypressCi extends Task<{ plugin: typeof CypressSchema }> { - async run(): Promise { - const reviewState = readState('review') - const cypressEnv: Record = {} - if (reviewState && reviewState.appName) { - cypressEnv.CYPRESS_BASE_URL = `https://${reviewState.appName}.herokuapp.com` - cypressEnv.CYPRESS_REVIEW_APP = 'true' - } else { - cypressEnv.CYPRESS_BASE_URL = `https://${process.env.CY_CUSTOM_DOMAIN_STAGING}` - } - - this.logger.info(`running cypress against ${cypressEnv.CYPRESS_BASEURL}`) - const testProcess = spawn('cypress', ['run'], { env: { ...process.env, ...cypressEnv } }) - hookFork(this.logger, 'cypress', testProcess) - return waitOnExit('cypress', testProcess) - } -} diff --git a/plugins/cypress/src/tasks/cypress.ts b/plugins/cypress/src/tasks/cypress.ts new file mode 100644 index 000000000..21eedf063 --- /dev/null +++ b/plugins/cypress/src/tasks/cypress.ts @@ -0,0 +1,37 @@ +import { spawn } from 'child_process' +import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' +import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' +import { readState } from '@dotcom-tool-kit/state' +import { Task } from '@dotcom-tool-kit/base' +import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' + +export default class Cypress extends Task<{ plugin: typeof CypressSchema }> { + async run(): Promise { + const reviewState = readState('review') + const appState = reviewState ?? readState('staging') + const cypressEnv: Record = {} + let dopplerEnv = {} + + if (appState) { + cypressEnv.CYPRESS_BASE_URL = appState.url ? appState.url : `https://${appState.appName}.herokuapp.com` + + if (reviewState) { + cypressEnv.CYPRESS_REVIEW_APP = 'true' + } + } else { + if (this.pluginOptions.localUrl) { + cypressEnv.CYPRESS_BASE_URL = this.pluginOptions.localUrl + } + + const doppler = new DopplerEnvVars(this.logger, 'dev') + dopplerEnv = await doppler.get() + } + + this.logger.info( + 'running cypress' + (cypressEnv.CYPRESS_BASE_URL ? ` against ${cypressEnv.CYPRESS_BASE_URL}` : '') + ) + const testProcess = spawn('cypress', ['run'], { env: { ...process.env, ...dopplerEnv, ...cypressEnv } }) + hookFork(this.logger, 'cypress', testProcess) + return waitOnExit('cypress', testProcess) + } +} diff --git a/plugins/cypress/src/tasks/local.ts b/plugins/cypress/src/tasks/local.ts deleted file mode 100644 index cbdbc9454..000000000 --- a/plugins/cypress/src/tasks/local.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { spawn } from 'child_process' -import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' -import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' -import { readState } from '@dotcom-tool-kit/state' -import { Task } from '@dotcom-tool-kit/base' -import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' - -export default class CypressLocal extends Task<{ plugin: typeof CypressSchema }> { - async run(): Promise { - const cypressEnv: Record = {} - if (this.pluginOptions.localUrl) { - cypressEnv.CYPRESS_BASE_URL = this.pluginOptions.localUrl - } - - const doppler = new DopplerEnvVars(this.logger, 'dev') - const dopplerEnv = await doppler.get() - - const env = { ...process.env, ...dopplerEnv, ...cypressEnv } - this.logger.info('running cypress' + (env.CYPRESS_BASE_URL ? ` against ${env.CYPRESS_BASE_URL}` : '')) - const testProcess = spawn('cypress', ['run'], { env }) - hookFork(this.logger, 'cypress', testProcess) - return waitOnExit('cypress', testProcess) - } -} From 8324d5fec839d12b034f34ead35d62e441b60a8c Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 18:05:29 +0100 Subject: [PATCH 152/321] feat: add watch, noEmit and build options to typescript task --- lib/schemas/src/tasks/typescript.ts | 5 ++++- plugins/typescript/src/tasks/typescript.ts | 16 ++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/schemas/src/tasks/typescript.ts b/lib/schemas/src/tasks/typescript.ts index af2868d38..804107432 100644 --- a/lib/schemas/src/tasks/typescript.ts +++ b/lib/schemas/src/tasks/typescript.ts @@ -1,7 +1,10 @@ import { z } from 'zod' export const TypeScriptSchema = z.object({ - configPath: z.string().optional() + configPath: z.string().optional(), + build: z.boolean().default(false), + watch: z.boolean().default(false), + noEmit: z.boolean().default(false) }) export type TypeScriptOptions = z.infer diff --git a/plugins/typescript/src/tasks/typescript.ts b/plugins/typescript/src/tasks/typescript.ts index 048d4ab7b..883b3b7b7 100644 --- a/plugins/typescript/src/tasks/typescript.ts +++ b/plugins/typescript/src/tasks/typescript.ts @@ -7,11 +7,23 @@ const tscPath = require.resolve('typescript/bin/tsc') export default class TypeScript extends Task<{ task: typeof TypeScriptSchema }> { async run(): Promise { - // TODO: add monorepo support with --build option const args = [] + // TODO:KB:20240408 refactor this + if (this.options.build) { + args.push('--build') + } + + if (this.options.watch) { + args.push('--watch') + } + + if (this.options.noEmit) { + args.push('--noEmit') + } + if (this.options.configPath) { - args.unshift('--project', this.options.configPath) + args.push('--project', this.options.configPath) } const child = fork(tscPath, args, { silent: true }) From e9d11ef13ac83e567d049aa66f2878eb77d3de1c Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 18:11:00 +0100 Subject: [PATCH 153/321] feat!: move cypress localUrl plugin option to a url task option and change precedence --- lib/schemas/src/plugins.ts | 2 -- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/{plugins => tasks}/cypress.ts | 2 +- plugins/cypress/src/tasks/cypress.ts | 12 ++++++------ 4 files changed, 10 insertions(+), 10 deletions(-) rename lib/schemas/src/{plugins => tasks}/cypress.ts (82%) diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index aab232075..fb669de6f 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -1,5 +1,4 @@ import { CircleCISchema } from './plugins/circleci' -import { CypressSchema } from './plugins/cypress' import { DopplerSchema } from './plugins/doppler' import { RootSchema } from './plugins/dotcom-tool-kit' import { HerokuSchema } from './plugins/heroku' @@ -12,7 +11,6 @@ import { type InferSchemaOptions } from './infer' export const PluginSchemas = { 'app root': RootSchema, '@dotcom-tool-kit/circleci': CircleCISchema, - '@dotcom-tool-kit/cypress': CypressSchema, '@dotcom-tool-kit/doppler': DopplerSchema, '@dotcom-tool-kit/heroku': HerokuSchema, '@dotcom-tool-kit/lint-staged-npm': LintStagedNpmSchema, diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index c89dd5bb5..4f4d01b38 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -11,6 +11,7 @@ import { TypeScriptSchema } from './tasks/typescript' import { UploadAssetsToS3Schema } from './tasks/upload-assets-to-s3' import { WebpackSchema } from './tasks/webpack' import { SmokeTestSchema } from './tasks/n-test' +import { CypressSchema } from './tasks/cypress' export const TaskSchemas = { Babel: BabelSchema, @@ -24,7 +25,8 @@ export const TaskSchemas = { TypeScript: TypeScriptSchema, UploadAssetsToS3: UploadAssetsToS3Schema, Webpack: WebpackSchema, - NTest: SmokeTestSchema + NTest: SmokeTestSchema, + Cypress: CypressSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/plugins/cypress.ts b/lib/schemas/src/tasks/cypress.ts similarity index 82% rename from lib/schemas/src/plugins/cypress.ts rename to lib/schemas/src/tasks/cypress.ts index d8788ace4..d13485cf9 100644 --- a/lib/schemas/src/plugins/cypress.ts +++ b/lib/schemas/src/tasks/cypress.ts @@ -1,7 +1,7 @@ import { z } from 'zod' export const CypressSchema = z.object({ - localUrl: z.string().optional() + url: z.string().optional() }) export type CypressOptions = z.infer diff --git a/plugins/cypress/src/tasks/cypress.ts b/plugins/cypress/src/tasks/cypress.ts index 21eedf063..11b9b86d9 100644 --- a/plugins/cypress/src/tasks/cypress.ts +++ b/plugins/cypress/src/tasks/cypress.ts @@ -3,15 +3,19 @@ import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { readState } from '@dotcom-tool-kit/state' import { Task } from '@dotcom-tool-kit/base' -import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/plugins/cypress' +import { CypressSchema } from '@dotcom-tool-kit/schemas/lib/tasks/cypress' -export default class Cypress extends Task<{ plugin: typeof CypressSchema }> { +export default class Cypress extends Task<{ task: typeof CypressSchema }> { async run(): Promise { const reviewState = readState('review') const appState = reviewState ?? readState('staging') const cypressEnv: Record = {} let dopplerEnv = {} + if (this.options.url) { + cypressEnv.CYPRESS_BASE_URL = this.options.url + } + if (appState) { cypressEnv.CYPRESS_BASE_URL = appState.url ? appState.url : `https://${appState.appName}.herokuapp.com` @@ -19,10 +23,6 @@ export default class Cypress extends Task<{ plugin: typeof CypressSchema }> { cypressEnv.CYPRESS_REVIEW_APP = 'true' } } else { - if (this.pluginOptions.localUrl) { - cypressEnv.CYPRESS_BASE_URL = this.pluginOptions.localUrl - } - const doppler = new DopplerEnvVars(this.logger, 'dev') dopplerEnv = await doppler.get() } From 9653311b8d9424327b6f217d626389674472d332 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 8 Apr 2024 18:28:53 +0100 Subject: [PATCH 154/321] feat!: split heroku options into plugin-wide and heroku production task-specific --- lib/schemas/src/plugins/heroku.ts | 135 +-------------------- lib/schemas/src/tasks.ts | 4 +- lib/schemas/src/tasks/heroku-production.ts | 135 +++++++++++++++++++++ plugins/heroku/src/tasks/production.ts | 8 +- 4 files changed, 148 insertions(+), 134 deletions(-) create mode 100644 lib/schemas/src/tasks/heroku-production.ts diff --git a/lib/schemas/src/plugins/heroku.ts b/lib/schemas/src/plugins/heroku.ts index 57783457d..d6e2bc8cd 100644 --- a/lib/schemas/src/plugins/heroku.ts +++ b/lib/schemas/src/plugins/heroku.ts @@ -1,142 +1,15 @@ -import { SchemaPromptGenerator, PromptGenerators } from '../prompts' - -import { waitOnExit } from '@dotcom-tool-kit/logger' - -import { spawn } from 'node:child_process' - -import type { Logger } from 'winston' +import { PromptGenerators } from '../prompts' import { z } from 'zod' -export const HerokuScalingSchema = z.record( - z.record( - z.object({ - size: z.string(), - quantity: z.number() - }) - ) -) -export type HerokuScaling = z.infer - -const HerokuDynoList = z.array( - z.object({ - size: z.string(), - state: z.string(), - type: z.string() - }) -) -type HerokuDynoList = z.infer - -const getDynos = async (logger: Logger, appName: string): Promise => { - // call the Heroku CLI so we can use the user's personal API token rather - // than sharing one that might be rate-limited/compromised - const herokuChild = spawn('heroku', ['ps', '--json', '-a', appName], { - // If the user isn't logged in they will get an error printed to stderr, - // with a call to login confirmed by stdin. The JSON result will get - // printed to stdout which is the only thing we want. - stdio: ['inherit', 'pipe', 'inherit'] - }) - let resp = '' - herokuChild.stdout.on('data', (data) => (resp += data)) - await waitOnExit('heroku', herokuChild) - // if the user logs in as part of the heroku ps call their username will be - // (obnoxiously) printed to stdout before the well-formatted JSON is printed - if (resp.startsWith('Logged in')) { - resp = resp.slice(resp.indexOf('\n') + 1) - } - return HerokuDynoList.parse(JSON.parse(resp)) -} - -const scaling: SchemaPromptGenerator = async (logger, prompt, onCancel, bizOpsSystem) => { - logger.error( - "you must specify the scaling for each of the production Heroku apps in your pipeline, but we'll try and guess your previous configuration first. you may have to sign into the Heroku CLI to do this" - ) - let scaling: HerokuScaling = {} - let allAppsConfigured = false - if (bizOpsSystem?.herokuApps.length ?? 0 > 0) { - /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- - * we just checked whether the bizOpsSystem variable is defined - **/ - for (const { code } of bizOpsSystem!.herokuApps) { - const dynos = await getDynos(logger, code) - const upDynos = dynos.filter(({ state }) => state === 'up') - const quantity = upDynos.length - if (quantity > 0) { - scaling[code] = { - [upDynos[0].type]: { size: upDynos[0].size.toLowerCase(), quantity } - } - } - } - const { confirmGuess } = await prompt( - { - name: 'confirmGuess', - type: 'confirm', - initial: true, - message: `based on Biz Ops and the Heroku API, we think your heroku plugin settings should be:\n${JSON.stringify( - scaling, - undefined, - 2 - )}\ndoes this look correct? if you say no you can enter the options manually instead` - }, - { onCancel } - ) - if (!confirmGuess) { - scaling = {} - } - allAppsConfigured = confirmGuess - } - while (!allAppsConfigured) { - const { app } = await prompt( - { - name: 'app', - type: 'text', - message: - 'Enter the name of the production Heroku app to configure. You can find the app name and resource details at https://dashboard.heroku.com/apps/[APP_NAME].' - }, - { onCancel } - ) - const { processType, size, quantity, moreApps } = await prompt( - [ - { - name: 'processType', - type: 'text', - initial: 'web', - message: `What is the process type of ${app}?` - }, - { - name: 'size', - type: 'text', - initial: 'standard-1X', - message: `What should the resource size of ${app} be?` - }, - { - name: 'quantity', - type: 'number', - message: `What should the number of dynos for ${app} be?` - }, - { - name: 'moreApps', - type: 'confirm', - message: 'Are there more production Heroku apps in this pipeline?' - } - ], - { onCancel } - ) - scaling[app] = { [processType]: { size, quantity } } - allAppsConfigured = !moreApps - } - return scaling -} - export const HerokuSchema = z.object({ pipeline: z.string().describe('this can be found at https://dashboard.heroku.com/pipelines/[APP_ID]'), - systemCode: z.string().describe('this can be found at https://biz-ops.in.ft.com/System/[APP_NAME]'), - scaling: HerokuScalingSchema + systemCode: z.string().describe('this can be found at https://biz-ops.in.ft.com/System/[APP_NAME]') }) + export type HerokuOptions = z.infer export const Schema = HerokuSchema export const generators: PromptGenerators = { pipeline: async (logger, prompt, onCancel, bizOpsSystem) => bizOpsSystem?.herokuApps[0]?.pipelineName, - systemCode: async (logger, prompt, onCancel, bizOpsSystem) => bizOpsSystem?.code, - scaling + systemCode: async (logger, prompt, onCancel, bizOpsSystem) => bizOpsSystem?.code } diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 4f4d01b38..c9d2de134 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -12,6 +12,7 @@ import { UploadAssetsToS3Schema } from './tasks/upload-assets-to-s3' import { WebpackSchema } from './tasks/webpack' import { SmokeTestSchema } from './tasks/n-test' import { CypressSchema } from './tasks/cypress' +import { HerokuProductionSchema } from './tasks/heroku-production' export const TaskSchemas = { Babel: BabelSchema, @@ -26,7 +27,8 @@ export const TaskSchemas = { UploadAssetsToS3: UploadAssetsToS3Schema, Webpack: WebpackSchema, NTest: SmokeTestSchema, - Cypress: CypressSchema + Cypress: CypressSchema, + HerokuProduction: HerokuProductionSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/tasks/heroku-production.ts b/lib/schemas/src/tasks/heroku-production.ts new file mode 100644 index 000000000..fccb575ba --- /dev/null +++ b/lib/schemas/src/tasks/heroku-production.ts @@ -0,0 +1,135 @@ +import { z } from 'zod' +import { PromptGenerators, SchemaPromptGenerator } from '../prompts' +import type { Logger } from 'winston' +import { spawn } from 'node:child_process' +import { waitOnExit } from '@dotcom-tool-kit/logger' + +const HerokuDynoList = z.array( + z.object({ + size: z.string(), + state: z.string(), + type: z.string() + }) +) + +type HerokuDynoList = z.infer + +const getDynos = async (logger: Logger, appName: string): Promise => { + // call the Heroku CLI so we can use the user's personal API token rather + // than sharing one that might be rate-limited/compromised + const herokuChild = spawn('heroku', ['ps', '--json', '-a', appName], { + // If the user isn't logged in they will get an error printed to stderr, + // with a call to login confirmed by stdin. The JSON result will get + // printed to stdout which is the only thing we want. + stdio: ['inherit', 'pipe', 'inherit'] + }) + let resp = '' + herokuChild.stdout.on('data', (data) => (resp += data)) + await waitOnExit('heroku', herokuChild) + // if the user logs in as part of the heroku ps call their username will be + // (obnoxiously) printed to stdout before the well-formatted JSON is printed + if (resp.startsWith('Logged in')) { + resp = resp.slice(resp.indexOf('\n') + 1) + } + return HerokuDynoList.parse(JSON.parse(resp)) +} + +const scaling: SchemaPromptGenerator = async (logger, prompt, onCancel, bizOpsSystem) => { + logger.error( + "you must specify the scaling for each of the production Heroku apps in your pipeline, but we'll try and guess your previous configuration first. you may have to sign into the Heroku CLI to do this" + ) + let scaling: HerokuScaling = {} + let allAppsConfigured = false + if (bizOpsSystem?.herokuApps.length ?? 0 > 0) { + /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- + * we just checked whether the bizOpsSystem variable is defined + **/ + for (const { code } of bizOpsSystem!.herokuApps) { + const dynos = await getDynos(logger, code) + const upDynos = dynos.filter(({ state }) => state === 'up') + const quantity = upDynos.length + if (quantity > 0) { + scaling[code] = { + [upDynos[0].type]: { size: upDynos[0].size.toLowerCase(), quantity } + } + } + } + const { confirmGuess } = await prompt( + { + name: 'confirmGuess', + type: 'confirm', + initial: true, + message: `based on Biz Ops and the Heroku API, we think your heroku plugin settings should be:\n${JSON.stringify( + scaling, + undefined, + 2 + )}\ndoes this look correct? if you say no you can enter the options manually instead` + }, + { onCancel } + ) + if (!confirmGuess) { + scaling = {} + } + allAppsConfigured = confirmGuess + } + while (!allAppsConfigured) { + const { app } = await prompt( + { + name: 'app', + type: 'text', + message: + 'Enter the name of the production Heroku app to configure. You can find the app name and resource details at https://dashboard.heroku.com/apps/[APP_NAME].' + }, + { onCancel } + ) + const { processType, size, quantity, moreApps } = await prompt( + [ + { + name: 'processType', + type: 'text', + initial: 'web', + message: `What is the process type of ${app}?` + }, + { + name: 'size', + type: 'text', + initial: 'standard-1X', + message: `What should the resource size of ${app} be?` + }, + { + name: 'quantity', + type: 'number', + message: `What should the number of dynos for ${app} be?` + }, + { + name: 'moreApps', + type: 'confirm', + message: 'Are there more production Heroku apps in this pipeline?' + } + ], + { onCancel } + ) + scaling[app] = { [processType]: { size, quantity } } + allAppsConfigured = !moreApps + } + return scaling +} + +export const HerokuScalingSchema = z.record( + z.record( + z.object({ + size: z.string(), + quantity: z.number() + }) + ) +) + +export type HerokuScaling = z.infer + +export const HerokuProductionSchema = z.object({ + scaling: HerokuScalingSchema +}) + +export const generators: PromptGenerators = { + scaling +} diff --git a/plugins/heroku/src/tasks/production.ts b/plugins/heroku/src/tasks/production.ts index 97badffb5..feb7b61f4 100644 --- a/plugins/heroku/src/tasks/production.ts +++ b/plugins/heroku/src/tasks/production.ts @@ -7,8 +7,12 @@ import type { HerokuApiResGetApp } from 'heroku-client' import heroku, { extractHerokuError } from '../herokuClient' import { scaleDyno } from '../scaleDyno' import { promoteStagingToProduction } from '../promoteStagingToProduction' +import { HerokuProductionSchema } from '@dotcom-tool-kit/schemas/src/tasks/heroku-production' -export default class HerokuProduction extends Task<{ plugin: typeof HerokuSchema }> { +export default class HerokuProduction extends Task<{ + plugin: typeof HerokuSchema + task: typeof HerokuProductionSchema +}> { static description = '' async run(): Promise { @@ -20,7 +24,7 @@ export default class HerokuProduction extends Task<{ plugin: typeof HerokuSchema } const { slugId } = state - const { scaling } = this.pluginOptions + const { scaling } = this.options const scale = async () => { for (const [appName, typeConfig] of Object.entries(scaling)) { From 5d3948960cb8a96f85728123f35add35b75022a2 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 08:49:26 +0100 Subject: [PATCH 155/321] feat!: rename serverless useVault option to useDoppler --- lib/schemas/src/plugins/serverless.ts | 3 ++- plugins/serverless/src/tasks/deploy.ts | 4 ++-- plugins/serverless/src/tasks/provision.ts | 4 ++-- plugins/serverless/src/tasks/run.ts | 4 ++-- plugins/serverless/src/tasks/teardown.ts | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/schemas/src/plugins/serverless.ts b/lib/schemas/src/plugins/serverless.ts index 310c51e47..e35b795a8 100644 --- a/lib/schemas/src/plugins/serverless.ts +++ b/lib/schemas/src/plugins/serverless.ts @@ -6,10 +6,11 @@ export const ServerlessSchema = z.object({ systemCode: z.string(), regions: z.array(z.string()).default(['eu-west-1']), configPath: z.string().optional(), - useVault: z.boolean().default(true), + useDoppler: z.boolean().default(true), ports: z.number().array().default([3001, 3002, 3003]), buildNumVariable: z.string().default('CIRCLE_BUILD_NUM') }) + export type ServerlessOptions = z.infer export const Schema = ServerlessSchema diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index 861d00018..447795c09 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -10,7 +10,7 @@ export default class ServerlessDeploy extends Task<{ plugin: typeof ServerlessSc static description = 'Deploys on AWS' async run(): Promise { - const { useVault, configPath, buildNumVariable, regions, systemCode } = this.pluginOptions + const { useDoppler, configPath, buildNumVariable, regions, systemCode } = this.pluginOptions const buildNum = process.env[buildNumVariable] if (buildNum === undefined) { @@ -28,7 +28,7 @@ export default class ServerlessDeploy extends Task<{ plugin: typeof ServerlessSc // skip this call if we find the project has already added options for // doppler in the Tool Kit configuration. const migratedToolKitToDoppler = Boolean(getOptions('@dotcom-tool-kit/doppler')?.project) - if (useVault && !migratedToolKitToDoppler) { + if (useDoppler && !migratedToolKitToDoppler) { const dopplerCi = new DopplerEnvVars(this.logger, 'ci') const vaultCi = await dopplerCi.fallbackToVault() // HACK:20231023:IM don't read secrets when the project has already diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index 2bbdb78c5..a8db43d08 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -11,7 +11,7 @@ export default class ServerlessProvision extends Task<{ plugin: typeof Serverles static description = 'Provisions a job on AWS' async run(): Promise { - const { useVault, configPath, buildNumVariable, systemCode, regions } = this.pluginOptions + const { useDoppler, configPath, buildNumVariable, systemCode, regions } = this.pluginOptions const buildNum = process.env[buildNumVariable] if (buildNum === undefined) { @@ -29,7 +29,7 @@ export default class ServerlessProvision extends Task<{ plugin: typeof Serverles // skip this call if we find the project has already added options for // doppler in the Tool Kit configuration. const migratedToolKitToDoppler = Boolean(getOptions('@dotcom-tool-kit/doppler')?.project) - if (useVault && !migratedToolKitToDoppler) { + if (useDoppler && !migratedToolKitToDoppler) { const dopplerCi = new DopplerEnvVars(this.logger, 'ci') const vaultCi = await dopplerCi.fallbackToVault() // HACK:20231023:IM don't read secrets when the project has already diff --git a/plugins/serverless/src/tasks/run.ts b/plugins/serverless/src/tasks/run.ts index df110de1a..9f7d9b91d 100644 --- a/plugins/serverless/src/tasks/run.ts +++ b/plugins/serverless/src/tasks/run.ts @@ -10,11 +10,11 @@ export default class ServerlessRun extends Task<{ plugin: typeof ServerlessSchem static description = 'Run serverless functions locally' async run(): Promise { - const { useVault, ports, configPath } = this.pluginOptions + const { useDoppler, ports, configPath } = this.pluginOptions let dopplerEnv = {} - if (useVault) { + if (useDoppler) { const doppler = new DopplerEnvVars(this.logger, 'dev') dopplerEnv = await doppler.get() diff --git a/plugins/serverless/src/tasks/teardown.ts b/plugins/serverless/src/tasks/teardown.ts index db52f9b7d..04232c1c3 100644 --- a/plugins/serverless/src/tasks/teardown.ts +++ b/plugins/serverless/src/tasks/teardown.ts @@ -11,7 +11,7 @@ export default class ServerlessTeardown extends Task<{ plugin: typeof Serverless static description = 'Teardown existing serverless functions' async run(): Promise { - const { useVault, configPath, regions, systemCode } = this.pluginOptions + const { useDoppler, configPath, regions, systemCode } = this.pluginOptions const reviewState = readState('review') @@ -28,7 +28,7 @@ export default class ServerlessTeardown extends Task<{ plugin: typeof Serverless // skip this call if we find the project has already added options for // doppler in the Tool Kit configuration. const migratedToolKitToDoppler = Boolean(getOptions('@dotcom-tool-kit/doppler')?.project) - if (useVault && !migratedToolKitToDoppler) { + if (useDoppler && !migratedToolKitToDoppler) { const dopplerCi = new DopplerEnvVars(this.logger, 'ci') const vaultCi = await dopplerCi.fallbackToVault() // HACK:20231023:IM don't read secrets when the project has already From bf9fa136d2dd21a6f2590d5b0b5082be7ffd5983 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 09:48:18 +0100 Subject: [PATCH 156/321] feat!: remove serverless buildNumVariable in favour of populating it via CI state --- lib/schemas/src/plugins/serverless.ts | 3 +-- lib/state/src/index.ts | 3 ++- plugins/circleci/src/init-env-vars.ts | 3 ++- plugins/serverless/src/tasks/deploy.ts | 12 ++--------- plugins/serverless/src/tasks/provision.ts | 26 +++++++++++++++++------ 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/lib/schemas/src/plugins/serverless.ts b/lib/schemas/src/plugins/serverless.ts index e35b795a8..016d0cff9 100644 --- a/lib/schemas/src/plugins/serverless.ts +++ b/lib/schemas/src/plugins/serverless.ts @@ -7,8 +7,7 @@ export const ServerlessSchema = z.object({ regions: z.array(z.string()).default(['eu-west-1']), configPath: z.string().optional(), useDoppler: z.boolean().default(true), - ports: z.number().array().default([3001, 3002, 3003]), - buildNumVariable: z.string().default('CIRCLE_BUILD_NUM') + ports: z.number().array().default([3001, 3002, 3003]) }) export type ServerlessOptions = z.infer diff --git a/lib/state/src/index.ts b/lib/state/src/index.ts index 62b14747e..56657f09b 100644 --- a/lib/state/src/index.ts +++ b/lib/state/src/index.ts @@ -5,13 +5,14 @@ const target = process.env.INIT_CWD || process.cwd() const stateDir = target ? path.join(target, '.toolkitstate') : '.toolkitstate' export const configPaths = ['.toolkitrc.yml', 'package.json', '.circleci/config.yml'] as const -type InstallState = Record +type InstallState = Record<(typeof configPaths)[number], string> interface CIState { repo: string branch: string version: string tag: string + buildNumber: string } export interface ReviewState { diff --git a/plugins/circleci/src/init-env-vars.ts b/plugins/circleci/src/init-env-vars.ts index 20a32862b..81b611e16 100644 --- a/plugins/circleci/src/init-env-vars.ts +++ b/plugins/circleci/src/init-env-vars.ts @@ -7,7 +7,8 @@ export default class CircleCIEnvVars extends Init { branch: process.env.CIRCLE_BRANCH, repo: process.env.CIRCLE_PROJECT_REPONAME, version: process.env.CIRCLE_SHA1, - tag: process.env.CIRCLE_TAG + tag: process.env.CIRCLE_TAG, + buildNumber: process.env.CIRCLE_BUILD_NUM } if (process.env.CIRCLECI) { diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index 447795c09..8a64bee18 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -5,21 +5,13 @@ import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverles import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { getOptions } from '@dotcom-tool-kit/options' import { spawn } from 'child_process' +import { readState } from '@dotcom-tool-kit/state' export default class ServerlessDeploy extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Deploys on AWS' async run(): Promise { - const { useDoppler, configPath, buildNumVariable, regions, systemCode } = this.pluginOptions - const buildNum = process.env[buildNumVariable] - - if (buildNum === undefined) { - throw new ToolKitError( - `the ${styles.task('ServerlessDeploy')} task requires the ${styles.code( - `$${buildNumVariable}` - )} environment variable to be defined` - ) - } + const { useDoppler, configPath, regions, systemCode } = this.pluginOptions let vaultEnv = {} // HACK:20231124:IM We need to call Vault to check whether a project has diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index a8db43d08..fea681eca 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -5,23 +5,35 @@ import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverles import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { spawn } from 'child_process' import { getOptions } from '@dotcom-tool-kit/options' -import { writeState } from '@dotcom-tool-kit/state' +import { readState, writeState } from '@dotcom-tool-kit/state' export default class ServerlessProvision extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Provisions a job on AWS' async run(): Promise { - const { useDoppler, configPath, buildNumVariable, systemCode, regions } = this.pluginOptions - const buildNum = process.env[buildNumVariable] + const { useDoppler, configPath, systemCode, regions } = this.pluginOptions + const ciState = readState('ci') - if (buildNum === undefined) { + if (!ciState) { throw new ToolKitError( - `the ${styles.task('ServerlessProvision')} task requires the ${styles.code( - `$${buildNumVariable}` - )} environment variable to be defined` + `the ${styles.task( + 'ServerlessDeploy' + )} should be run in CI, but no CI state was found. check you have a plugin installed that initialises the CI state.` ) } + const buildNum = ciState?.buildNumber + + if (!buildNum) { + const error = new ToolKitError( + `the ${styles.task('ServerlessDeploy')} requires a CI build number in the CI state.` + ) + + error.details = `this is provided by plugins such as ${styles.plugin( + 'circleci' + )}, which populates it from the CIRCLE_BUILD_NUM environment variable.` + } + let vaultEnv = {} // HACK:20231124:IM We need to call Vault to check whether a project has // migrated to Doppler yet, and sync Vault secrets if it hasn't, but this From ad60eee53c9af71b2455ca041cae4a669a40a245 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 11:50:24 +0100 Subject: [PATCH 157/321] chore!: remove unused legacy vault/doppler support from serverless deploy/provision/teardown tasks --- plugins/serverless/src/tasks/deploy.ts | 32 +++-------------------- plugins/serverless/src/tasks/provision.ts | 28 ++------------------ plugins/serverless/src/tasks/teardown.ts | 28 ++------------------ 3 files changed, 7 insertions(+), 81 deletions(-) diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index 8a64bee18..54cfb2c33 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -1,36 +1,13 @@ -import { ToolKitError } from '@dotcom-tool-kit/error' -import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' +import { hookFork, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' -import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' -import { getOptions } from '@dotcom-tool-kit/options' import { spawn } from 'child_process' -import { readState } from '@dotcom-tool-kit/state' export default class ServerlessDeploy extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Deploys on AWS' async run(): Promise { - const { useDoppler, configPath, regions, systemCode } = this.pluginOptions - - let vaultEnv = {} - // HACK:20231124:IM We need to call Vault to check whether a project has - // migrated to Doppler yet, and sync Vault secrets if it hasn't, but this - // logic should be removed entirely once we drop support for Vault. We can - // skip this call if we find the project has already added options for - // doppler in the Tool Kit configuration. - const migratedToolKitToDoppler = Boolean(getOptions('@dotcom-tool-kit/doppler')?.project) - if (useDoppler && !migratedToolKitToDoppler) { - const dopplerCi = new DopplerEnvVars(this.logger, 'ci') - const vaultCi = await dopplerCi.fallbackToVault() - // HACK:20231023:IM don't read secrets when the project has already - // migrated from Vault to Doppler – Doppler will instead sync secrets to - // Parameter Store for the Serverless config to reference - if (!vaultCi.MIGRATED_TO_DOPPLER) { - const dopplerEnvVars = new DopplerEnvVars(this.logger, 'prod') - vaultEnv = await dopplerEnvVars.fallbackToVault() - } - } + const { configPath, regions, systemCode } = this.pluginOptions for (const region of regions) { this.logger.verbose('starting the child serverless process...') @@ -48,10 +25,7 @@ export default class ServerlessDeploy extends Task<{ plugin: typeof ServerlessSc } const child = spawn('serverless', args, { - env: { - ...process.env, - ...vaultEnv - } + env: process.env }) hookFork(this.logger, 'serverless', child) diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index fea681eca..fc8634ca1 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -2,16 +2,14 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' -import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { spawn } from 'child_process' -import { getOptions } from '@dotcom-tool-kit/options' import { readState, writeState } from '@dotcom-tool-kit/state' export default class ServerlessProvision extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Provisions a job on AWS' async run(): Promise { - const { useDoppler, configPath, systemCode, regions } = this.pluginOptions + const { configPath, systemCode, regions } = this.pluginOptions const ciState = readState('ci') if (!ciState) { @@ -34,25 +32,6 @@ export default class ServerlessProvision extends Task<{ plugin: typeof Serverles )}, which populates it from the CIRCLE_BUILD_NUM environment variable.` } - let vaultEnv = {} - // HACK:20231124:IM We need to call Vault to check whether a project has - // migrated to Doppler yet, and sync Vault secrets if it hasn't, but this - // logic should be removed entirely once we drop support for Vault. We can - // skip this call if we find the project has already added options for - // doppler in the Tool Kit configuration. - const migratedToolKitToDoppler = Boolean(getOptions('@dotcom-tool-kit/doppler')?.project) - if (useDoppler && !migratedToolKitToDoppler) { - const dopplerCi = new DopplerEnvVars(this.logger, 'ci') - const vaultCi = await dopplerCi.fallbackToVault() - // HACK:20231023:IM don't read secrets when the project has already - // migrated from Vault to Doppler – Doppler will instead sync secrets to - // Parameter Store for the Serverless config to reference - if (!vaultCi.MIGRATED_TO_DOPPLER) { - const dopplerEnvVars = new DopplerEnvVars(this.logger, 'dev') - vaultEnv = await dopplerEnvVars.fallbackToVault() - } - } - const stageName = `ci${buildNum}` this.logger.verbose('starting the child serverless process...') @@ -70,10 +49,7 @@ export default class ServerlessProvision extends Task<{ plugin: typeof Serverles } const child = spawn('serverless', args, { - env: { - ...process.env, - ...vaultEnv - } + env: process.env }) hookFork(this.logger, 'serverless', child) diff --git a/plugins/serverless/src/tasks/teardown.ts b/plugins/serverless/src/tasks/teardown.ts index 04232c1c3..987a7c944 100644 --- a/plugins/serverless/src/tasks/teardown.ts +++ b/plugins/serverless/src/tasks/teardown.ts @@ -3,15 +3,13 @@ import { hookFork, styles, waitOnExit } from '@dotcom-tool-kit/logger' import { Task } from '@dotcom-tool-kit/base' import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' import { readState } from '@dotcom-tool-kit/state' -import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { spawn } from 'child_process' -import { getOptions } from '@dotcom-tool-kit/options' export default class ServerlessTeardown extends Task<{ plugin: typeof ServerlessSchema }> { static description = 'Teardown existing serverless functions' async run(): Promise { - const { useDoppler, configPath, regions, systemCode } = this.pluginOptions + const { configPath, regions, systemCode } = this.pluginOptions const reviewState = readState('review') @@ -21,25 +19,6 @@ export default class ServerlessTeardown extends Task<{ plugin: typeof Serverless ) } - let vaultEnv = {} - // HACK:20231124:IM We need to call Vault to check whether a project has - // migrated to Doppler yet, and sync Vault secrets if it hasn't, but this - // logic should be removed entirely once we drop support for Vault. We can - // skip this call if we find the project has already added options for - // doppler in the Tool Kit configuration. - const migratedToolKitToDoppler = Boolean(getOptions('@dotcom-tool-kit/doppler')?.project) - if (useDoppler && !migratedToolKitToDoppler) { - const dopplerCi = new DopplerEnvVars(this.logger, 'ci') - const vaultCi = await dopplerCi.fallbackToVault() - // HACK:20231023:IM don't read secrets when the project has already - // migrated from Vault to Doppler – Doppler will instead sync secrets to - // Parameter Store for the Serverless config to reference - if (!vaultCi.MIGRATED_TO_DOPPLER) { - const dopplerEnvVars = new DopplerEnvVars(this.logger, 'dev') - vaultEnv = await dopplerEnvVars.fallbackToVault() - } - } - this.logger.verbose('starting the child serverless process...') const args = [ @@ -56,10 +35,7 @@ export default class ServerlessTeardown extends Task<{ plugin: typeof Serverless } const child = spawn('serverless', args, { - env: { - ...process.env, - ...vaultEnv - } + env: process.env }) hookFork(this.logger, 'serverless', child) From 61fbaaec890b51861cedf6076691fa5dc1bc5873 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 11:54:12 +0100 Subject: [PATCH 158/321] feat!: move serverless run ports and useDoppler options to task options --- lib/schemas/src/plugins/serverless.ts | 4 +--- lib/schemas/src/tasks.ts | 4 +++- lib/schemas/src/tasks/serverless-run.ts | 10 ++++++++++ plugins/serverless/src/tasks/run.ts | 9 +++++++-- 4 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 lib/schemas/src/tasks/serverless-run.ts diff --git a/lib/schemas/src/plugins/serverless.ts b/lib/schemas/src/plugins/serverless.ts index 016d0cff9..f84ee7322 100644 --- a/lib/schemas/src/plugins/serverless.ts +++ b/lib/schemas/src/plugins/serverless.ts @@ -5,9 +5,7 @@ export const ServerlessSchema = z.object({ awsAccountId: z.string(), systemCode: z.string(), regions: z.array(z.string()).default(['eu-west-1']), - configPath: z.string().optional(), - useDoppler: z.boolean().default(true), - ports: z.number().array().default([3001, 3002, 3003]) + configPath: z.string().optional() }) export type ServerlessOptions = z.infer diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index c9d2de134..a258e1810 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -13,6 +13,7 @@ import { WebpackSchema } from './tasks/webpack' import { SmokeTestSchema } from './tasks/n-test' import { CypressSchema } from './tasks/cypress' import { HerokuProductionSchema } from './tasks/heroku-production' +import { ServerlessRunSchema } from './tasks/serverless-run' export const TaskSchemas = { Babel: BabelSchema, @@ -28,7 +29,8 @@ export const TaskSchemas = { Webpack: WebpackSchema, NTest: SmokeTestSchema, Cypress: CypressSchema, - HerokuProduction: HerokuProductionSchema + HerokuProduction: HerokuProductionSchema, + ServerlessRun: ServerlessRunSchema } export type TaskOptions = InferSchemaOptions diff --git a/lib/schemas/src/tasks/serverless-run.ts b/lib/schemas/src/tasks/serverless-run.ts new file mode 100644 index 000000000..872c26dcf --- /dev/null +++ b/lib/schemas/src/tasks/serverless-run.ts @@ -0,0 +1,10 @@ +import { z } from 'zod' + +export const ServerlessRunSchema = z.object({ + ports: z.number().array().default([3001, 3002, 3003]), + useDoppler: z.boolean().default(true) +}) + +export type ServerlessOptions = z.infer + +export const Schema = ServerlessRunSchema diff --git a/plugins/serverless/src/tasks/run.ts b/plugins/serverless/src/tasks/run.ts index 9f7d9b91d..df45b5b59 100644 --- a/plugins/serverless/src/tasks/run.ts +++ b/plugins/serverless/src/tasks/run.ts @@ -1,16 +1,21 @@ import { Task } from '@dotcom-tool-kit/base' import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverless' +import { ServerlessRunSchema } from '@dotcom-tool-kit/schemas/src/tasks/serverless-run' import { spawn } from 'child_process' import { DopplerEnvVars } from '@dotcom-tool-kit/doppler' import { hookConsole, hookFork } from '@dotcom-tool-kit/logger' import getPort from 'get-port' import waitPort from 'wait-port' -export default class ServerlessRun extends Task<{ plugin: typeof ServerlessSchema }> { +export default class ServerlessRun extends Task<{ + task: typeof ServerlessRunSchema + plugin: typeof ServerlessSchema +}> { static description = 'Run serverless functions locally' async run(): Promise { - const { useDoppler, ports, configPath } = this.pluginOptions + const { useDoppler, ports } = this.options + const { configPath } = this.pluginOptions let dopplerEnv = {} From e9ce311900d24c7df09edde16b58060f4ee50953 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 11:56:31 +0100 Subject: [PATCH 159/321] style: sort task schemas alphabetically --- lib/schemas/src/tasks.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index a258e1810..1380fb518 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -17,20 +17,20 @@ import { ServerlessRunSchema } from './tasks/serverless-run' export const TaskSchemas = { Babel: BabelSchema, + Cypress: CypressSchema, Eslint: ESLintSchema, + HerokuProduction: HerokuProductionSchema, Jest: JestSchema, Mocha: MochaSchema, Node: NodeSchema, Nodemon: NodemonSchema, + NTest: SmokeTestSchema, Pa11y: Pa11ySchema, Prettier: PrettierSchema, + ServerlessRun: ServerlessRunSchema, TypeScript: TypeScriptSchema, UploadAssetsToS3: UploadAssetsToS3Schema, - Webpack: WebpackSchema, - NTest: SmokeTestSchema, - Cypress: CypressSchema, - HerokuProduction: HerokuProductionSchema, - ServerlessRun: ServerlessRunSchema + Webpack: WebpackSchema } export type TaskOptions = InferSchemaOptions From 9d532fa2f9438cf2b518a62fb3b306c071656429 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 15:40:35 +0100 Subject: [PATCH 160/321] feat: add configPath option for eslint task --- lib/schemas/src/tasks/eslint.ts | 1 + plugins/eslint/src/tasks/eslint.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/schemas/src/tasks/eslint.ts b/lib/schemas/src/tasks/eslint.ts index 1941da917..daca70121 100644 --- a/lib/schemas/src/tasks/eslint.ts +++ b/lib/schemas/src/tasks/eslint.ts @@ -1,6 +1,7 @@ import { z } from 'zod' export const ESLintSchema = z.object({ + configPath: z.string().optional(), files: z.string().array().or(z.string()).default(['**/*.js']) }) diff --git a/plugins/eslint/src/tasks/eslint.ts b/plugins/eslint/src/tasks/eslint.ts index b130e5d0f..c2fb06cac 100644 --- a/plugins/eslint/src/tasks/eslint.ts +++ b/plugins/eslint/src/tasks/eslint.ts @@ -8,7 +8,7 @@ export default class Eslint extends Task<{ task: typeof ESLintSchema }> { static description = '' async run(files?: string[]): Promise { - const eslint = new ESLint() + const eslint = new ESLint({ overrideConfigFile: this.options.configPath }) const results = await eslint.lintFiles(files ?? this.options.files) const formatter = await eslint.loadFormatter('stylish') const resultText = formatter.format(results) From d9d6423f64a36857b8fb1e605f14503063826da4 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 16:51:05 +0100 Subject: [PATCH 161/321] test(eslint): use a temp dir for eslint test files and get tests passing --- package-lock.json | 48 +++++++++++++++++ package.json | 2 + plugins/eslint/test/files/.eslintrc.js | 14 ----- plugins/eslint/test/files/fail.js | 4 -- plugins/eslint/test/files/pass.js | 1 - plugins/eslint/test/tasks/eslint.test.ts | 68 +++++++++++++++++------- 6 files changed, 98 insertions(+), 39 deletions(-) delete mode 100644 plugins/eslint/test/files/.eslintrc.js delete mode 100644 plugins/eslint/test/files/fail.js delete mode 100644 plugins/eslint/test/files/pass.js diff --git a/package-lock.json b/package-lock.json index 09abf90b8..0b32efdfc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@tsconfig/node16": "^1.0.3", "@types/jest": "^27.4.0", "@types/node": "^16.18.23", + "@types/temp": "^0.9.4", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "check-engines": "^1.5.0", @@ -37,6 +38,7 @@ "lint-staged": "^10.5.4", "prettier": "^2.8.8", "release-please": "^15.0.0", + "temp": "^0.9.4", "ts-jest": "^27.1.3", "typescript": "~4.9.5" }, @@ -9873,6 +9875,15 @@ "@types/node": "*" } }, + "node_modules/@types/temp": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@types/temp/-/temp-0.9.4.tgz", + "integrity": "sha512-+VfWIwrlept2VBTj7Y2wQnI/Xfscy1u8Pyj/puYwss6V1IblXn1x7S0S9eFh6KyBolgLCm+rUFzhFAbdkR691g==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/tough-cookie": { "version": "4.0.2", "license": "MIT" @@ -26668,6 +26679,43 @@ } } }, + "node_modules/temp": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", + "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", + "dev": true, + "dependencies": { + "mkdirp": "^0.5.1", + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/terminal-link": { "version": "2.1.1", "license": "MIT", diff --git a/package.json b/package.json index 4346725ad..df07278d2 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@tsconfig/node16": "^1.0.3", "@types/jest": "^27.4.0", "@types/node": "^16.18.23", + "@types/temp": "^0.9.4", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "check-engines": "^1.5.0", @@ -38,6 +39,7 @@ "lint-staged": "^10.5.4", "prettier": "^2.8.8", "release-please": "^15.0.0", + "temp": "^0.9.4", "ts-jest": "^27.1.3", "typescript": "~4.9.5" }, diff --git a/plugins/eslint/test/files/.eslintrc.js b/plugins/eslint/test/files/.eslintrc.js deleted file mode 100644 index b44fe5bce..000000000 --- a/plugins/eslint/test/files/.eslintrc.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - env: { - commonjs: true, - es2021: true, - node: true - }, - extends: 'eslint:recommended', - overrides: [], - parserOptions: { - ecmaVersion: 'latest' - }, - rules: {}, - root: true -} diff --git a/plugins/eslint/test/files/fail.js b/plugins/eslint/test/files/fail.js deleted file mode 100644 index 7211b2c8a..000000000 --- a/plugins/eslint/test/files/fail.js +++ /dev/null @@ -1,4 +0,0 @@ -function lintFail() { - let test = 'hello?' - console.log(test) -} diff --git a/plugins/eslint/test/files/pass.js b/plugins/eslint/test/files/pass.js deleted file mode 100644 index 8d2f0971e..000000000 --- a/plugins/eslint/test/files/pass.js +++ /dev/null @@ -1 +0,0 @@ -1 + 1 diff --git a/plugins/eslint/test/tasks/eslint.test.ts b/plugins/eslint/test/tasks/eslint.test.ts index 789b7a380..7a9cdf201 100644 --- a/plugins/eslint/test/tasks/eslint.test.ts +++ b/plugins/eslint/test/tasks/eslint.test.ts @@ -1,34 +1,62 @@ -import { ToolKitError } from '@dotcom-tool-kit/error/lib' import { describe, it, expect } from '@jest/globals' import * as path from 'path' import winston, { Logger } from 'winston' import ESLint from '../../src/tasks/eslint' +import temp from 'temp' +import fs from 'fs/promises' -const logger = (winston as unknown) as Logger - -const testDirectory = path.join(__dirname, '../files') +const logger = winston as unknown as Logger describe('eslint', () => { + let testDirectory: string + + beforeAll(async () => { + testDirectory = await temp.mkdir('eslint') + + await fs.writeFile( + path.join(testDirectory, '.eslintrc.js'), + `module.exports = { + extends: 'eslint:recommended', + root: true + }` + ) + + await fs.writeFile(path.join(testDirectory, 'pass.js'), `1 + 1`) + await fs.writeFile(path.join(testDirectory, 'fail.js'), `undeclared`) + }) + + afterAll(async () => { + await temp.cleanup() + }) + it('should pass on correct file', async () => { - const task = new ESLint(logger, 'ESLint', { - options: { ignore: false, cwd: testDirectory }, - files: [path.join(testDirectory, 'pass.js')] - }) + const task = new ESLint( + logger, + 'ESLint', + {}, + { + configPath: path.join(testDirectory, '.eslintrc.js'), + files: [path.join(testDirectory, 'pass.js')] + } + ) - await task.run() + await expect(task.run()).resolves.toBeUndefined() }) it('should fail on linter error', async () => { - const task = new ESLint(logger, 'ESLint', { - options: { ignore: false, cwd: testDirectory }, - files: [path.join(testDirectory, 'fail.js')] - }) - - expect.assertions(1) - try { - await task.run() - } catch (err) { - if (err instanceof ToolKitError) expect(err.details).toContain('1 problem (1 error, 0 warnings)') - } + const task = new ESLint( + logger, + 'ESLint', + {}, + { + configPath: path.join(testDirectory, '.eslintrc.js'), + files: [path.join(testDirectory, 'fail.js')] + } + ) + + await expect(task.run()).rejects.toHaveProperty( + 'details', + expect.stringContaining('1 problem (1 error, 0 warnings)') + ) }) }) From 5594dca49c77fcfeee072d00c8f19a52e711bb07 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 16:53:38 +0100 Subject: [PATCH 162/321] test(babel): fix tests for new task constructor arg signature --- plugins/babel/test/tasks/babel.test.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/babel/test/tasks/babel.test.ts b/plugins/babel/test/tasks/babel.test.ts index 21d91557d..13f0851ce 100644 --- a/plugins/babel/test/tasks/babel.test.ts +++ b/plugins/babel/test/tasks/babel.test.ts @@ -1,10 +1,10 @@ import { beforeAll, describe, expect, it } from '@jest/globals' -import Babel from '../../src/tasks/development' +import Babel from '../../src/tasks/babel' import { promises as fs } from 'fs' import * as path from 'path' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger const testDirectory = path.join(__dirname, '../files') const outputPath = path.join(testDirectory, 'lib') @@ -17,11 +17,17 @@ describe('babel', () => { }) it('should transpile the file', async () => { - const task = new Babel(logger, 'Babel', { - files: path.join(testDirectory, 'index.js'), - outputPath, - configFile: path.join(testDirectory, 'babel.config.json') - }) + const task = new Babel( + logger, + 'Babel', + {}, + { + envName: 'development', + files: path.join(testDirectory, 'index.js'), + outputPath, + configFile: path.join(testDirectory, 'babel.config.json') + } + ) await task.run() const transpiled = await fs.readFile(path.join(outputPath, 'index.js'), 'utf8') expect(transpiled).toEqual(transpiledFixture) From 0716af2747498e173c7945d63d110173ad573df4 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 16:51:05 +0100 Subject: [PATCH 163/321] test(eslint): use a temp dir for eslint test files and get tests passing --- plugins/eslint/test/tasks/eslint.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/eslint/test/tasks/eslint.test.ts b/plugins/eslint/test/tasks/eslint.test.ts index 7a9cdf201..37008f3cb 100644 --- a/plugins/eslint/test/tasks/eslint.test.ts +++ b/plugins/eslint/test/tasks/eslint.test.ts @@ -7,6 +7,8 @@ import fs from 'fs/promises' const logger = winston as unknown as Logger +temp.track() + describe('eslint', () => { let testDirectory: string From dba63f7a61f47adfc296a4f40087014c3183c958 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 16:54:57 +0100 Subject: [PATCH 164/321] test(webpack): fix tests for new task constructor arg signature and options --- plugins/webpack/test/tasks/webpack.test.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/webpack/test/tasks/webpack.test.ts b/plugins/webpack/test/tasks/webpack.test.ts index 04fc5e206..04b135c0f 100644 --- a/plugins/webpack/test/tasks/webpack.test.ts +++ b/plugins/webpack/test/tasks/webpack.test.ts @@ -1,11 +1,10 @@ import { describe, jest, it, expect } from '@jest/globals' -import DevelopmentWebpack from '../../src/tasks/development' -import ProductionWebpack from '../../src/tasks/production' +import Webpack from '../../src/tasks/webpack' import { fork } from 'child_process' import EventEmitter from 'events' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger jest.mock('child_process', () => ({ fork: jest.fn(() => { @@ -26,7 +25,7 @@ describe('webpack', () => { describe('development', () => { it('should call webpack cli with correct arguments', async () => { const configPath = 'webpack.config.js' - const task = new DevelopmentWebpack(logger, 'DevelopmentWebpack', { configPath }) + const task = new Webpack(logger, 'Webpack', {}, { configPath, envName: 'development' }) await task.run() expect(fork).toBeCalledWith( @@ -40,7 +39,7 @@ describe('webpack', () => { describe('production', () => { it('should call webpack cli with correct arguments', async () => { const configPath = 'webpack.config.js' - const task = new ProductionWebpack(logger, 'ProductionWebpack', { configPath }) + const task = new Webpack(logger, 'Webpack', {}, { configPath, envName: 'production' }) await task.run() expect(fork).toBeCalledWith( @@ -57,7 +56,7 @@ describe('webpack', () => { process.allowedNodeEnvironmentFlags = { has: jest.fn(() => true) } as any const configPath = 'webpack.config.js' - const task = new ProductionWebpack(logger, 'ProductionWebpack', { configPath }) + const task = new Webpack(logger, 'Webpack', {}, { configPath, envName: 'production' }) await task.run() expect(mockedFork.mock.calls[0][2]?.execArgv).toEqual( @@ -70,7 +69,7 @@ describe('webpack', () => { process.allowedNodeEnvironmentFlags = { has: jest.fn(() => false) } as any const configPath = 'webpack.config.js' - const task = new ProductionWebpack(logger, 'ProductionWebpack', { configPath }) + const task = new Webpack(logger, 'Webpack', {}, { configPath, envName: 'production' }) await task.run() expect(mockedFork.mock.calls[0][2]?.execArgv).toEqual( From 2a4cc6e9daa4fe6575a357eb4e5d382d676ac519 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:01:38 +0100 Subject: [PATCH 165/321] refactor: more appropriate type for typescript options --- lib/schemas/src/tasks/typescript.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/schemas/src/tasks/typescript.ts b/lib/schemas/src/tasks/typescript.ts index 804107432..8f188eb14 100644 --- a/lib/schemas/src/tasks/typescript.ts +++ b/lib/schemas/src/tasks/typescript.ts @@ -2,9 +2,9 @@ import { z } from 'zod' export const TypeScriptSchema = z.object({ configPath: z.string().optional(), - build: z.boolean().default(false), - watch: z.boolean().default(false), - noEmit: z.boolean().default(false) + build: z.literal(true).optional(), + watch: z.literal(true).optional(), + noEmit: z.literal(true).optional() }) export type TypeScriptOptions = z.infer From 47a5c97d2497385ac880770370a936ed0eb000ca Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:01:51 +0100 Subject: [PATCH 166/321] test(typescript): update tests for new options --- .../typescript/test/tasks/typescript.test.ts | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/plugins/typescript/test/tasks/typescript.test.ts b/plugins/typescript/test/tasks/typescript.test.ts index dd1050db4..2cecff491 100644 --- a/plugins/typescript/test/tasks/typescript.test.ts +++ b/plugins/typescript/test/tasks/typescript.test.ts @@ -1,12 +1,10 @@ import { describe, jest, it, expect } from '@jest/globals' -import TypeScriptBuild from '../../src/tasks/build' -import TypeScriptWatch from '../../src/tasks/watch' -import TypeScriptTest from '../../src/tasks/test' +import TypeScript from '../../src/tasks/typescript' import { fork } from 'child_process' import EventEmitter from 'events' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger jest.mock('child_process', () => ({ fork: jest.fn(() => { @@ -24,36 +22,45 @@ const tscPath = require.resolve('typescript/bin/tsc') const configPath = 'tsconfig.json' describe('typescript', () => { - describe('correct arguments', () => { - it('should start tsc build with correct arguments', async () => { - const task = new TypeScriptBuild(logger, 'TypeScriptBuild', { configPath }) - await task.run() + it('should run tsc', async () => { + const task = new TypeScript(logger, 'TypeScript', {}, { configPath }) + await task.run() - expect(fork).toBeCalledWith(tscPath, ['--project', configPath], { silent: true }) - }) + expect(fork).toBeCalledWith(tscPath, ['--project', configPath], { silent: true }) + }) - it('should start tsc watch with correct arguments', async () => { - const task = new TypeScriptWatch(logger, 'TypeScriptWatch', { configPath }) - await task.run() + it('watch option should run tsc with --watch arg', async () => { + const task = new TypeScript(logger, 'TypeScript', {}, { configPath, watch: true }) + await task.run() - expect(fork).toBeCalledWith(tscPath, ['--project', configPath, '--watch'], { silent: true }) - }) + expect(fork).toBeCalledWith(tscPath, ['--watch', '--project', configPath], { silent: true }) + }) - it('should start tsc test with correct arguments', async () => { - const task = new TypeScriptTest(logger, 'TypeScriptTest', { configPath }) - await task.run() + it('noEmit option should run tsc with --noEmit arg', async () => { + const task = new TypeScript(logger, 'TypeScript', {}, { configPath, noEmit: true }) + await task.run() - expect(fork).toBeCalledWith(tscPath, ['--project', configPath, '--noEmit'], { silent: true }) - }) + expect(fork).toBeCalledWith(tscPath, ['--noEmit', '--project', configPath], { silent: true }) + }) + + it('build option should run tsc with --build arg', async () => { + const task = new TypeScript(logger, 'TypeScript', {}, { configPath, build: true }) + await task.run() + + expect(fork).toBeCalledWith(tscPath, ['--build', '--project', configPath], { silent: true }) + }) - it('should pass in extra arguments', async () => { - const extraArgs = ['--verbose', '--force'] - const task = new TypeScriptBuild(logger, 'TypeScriptBuild', { configPath, extraArgs }) - await task.run() + it('can combine options', async () => { + const task = new TypeScript( + logger, + 'TypeScript', + {}, + { configPath, build: true, watch: true, noEmit: true } + ) + await task.run() - expect(fork).toBeCalledWith(tscPath, ['--project', configPath, ...extraArgs], { - silent: true - }) + expect(fork).toBeCalledWith(tscPath, ['--build', '--watch', '--noEmit', '--project', configPath], { + silent: true }) }) }) From f0677219c15bac5da514fae6f1226317c5525e5d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:16:25 +0100 Subject: [PATCH 167/321] feat!: change jest "mode" option to a boolean "ci" option mode: "local" doesn't do anything --- lib/schemas/src/tasks/jest.ts | 2 +- plugins/jest/src/tasks/jest.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/schemas/src/tasks/jest.ts b/lib/schemas/src/tasks/jest.ts index 9d0e5187a..abbe98379 100644 --- a/lib/schemas/src/tasks/jest.ts +++ b/lib/schemas/src/tasks/jest.ts @@ -2,7 +2,7 @@ import { z } from 'zod' export const JestSchema = z.object({ configPath: z.string().optional(), - mode: z.union([z.literal('ci'), z.literal('local')]) + ci: z.literal(true).optional() }) export type JestOptions = z.infer diff --git a/plugins/jest/src/tasks/jest.ts b/plugins/jest/src/tasks/jest.ts index a0dbae631..341274e22 100644 --- a/plugins/jest/src/tasks/jest.ts +++ b/plugins/jest/src/tasks/jest.ts @@ -37,7 +37,7 @@ export default class Jest extends Task<{ task: typeof JestSchema }> { // TODO:20231107:IM we should probably refactor this plugin to move // CI-specific logic to be within the CI task module - if (this.options.mode === 'ci') { + if (this.options.ci) { args.push('--ci') // only relevant if running on CircleCI, other CI environments might handle // virtualisation completely differently From 039f81b08f2900bb796631c24cd78befc54cfca1 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:17:57 +0100 Subject: [PATCH 168/321] test(jest): update tests for new options --- plugins/jest/tests/jest-plugin.test.ts | 76 ++++++++++---------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/plugins/jest/tests/jest-plugin.test.ts b/plugins/jest/tests/jest-plugin.test.ts index 2a28d4e19..188bd6789 100644 --- a/plugins/jest/tests/jest-plugin.test.ts +++ b/plugins/jest/tests/jest-plugin.test.ts @@ -1,10 +1,9 @@ import { fork } from 'node:child_process' -import JestLocal from '../src/tasks/local' -import JestCI from '../src/tasks/ci' +import Jest from '../src/tasks/jest' import EventEmitter from 'events' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger jest.mock('node:child_process', () => ({ fork: jest.fn(() => { @@ -19,55 +18,36 @@ jest.mock('node:child_process', () => ({ jest.mock('@dotcom-tool-kit/logger') describe('jest plugin', () => { - describe('local', () => { - it('should call jest cli with configPath if configPath is passed in', async () => { - const jestLocal = new JestLocal(logger, 'JestLocal', { configPath: './src/jest.config.js' }) - await jestLocal.run() - - expect(fork).toBeCalledWith( - expect.any(String), - expect.arrayContaining(['--config=./src/jest.config.js']), - { - silent: true - } - ) - }) - - it('should call jest cli without configPath by default', async () => { - const jestLocal = new JestLocal(logger, 'JestLocal', {}) - await jestLocal.run() - - expect(fork).toBeCalledWith( - expect.any(String), - expect.not.arrayContaining([expect.stringContaining('--config')]), - { silent: true } - ) - }) + it('should call jest cli without configPath by default', async () => { + const jest = new Jest(logger, 'Jest', {}, {}) + await jest.run() + + expect(fork).toBeCalledWith( + expect.any(String), + expect.not.arrayContaining([expect.stringContaining('--config')]), + { silent: true } + ) }) - describe('ci', () => { - it('should call jest cli with configPath if configPath is passed in', async () => { - const jestCI = new JestCI(logger, 'JestCI', { configPath: './src/jest.config.js' }) - await jestCI.run() - - expect(fork).toBeCalledWith( - expect.any(String), - expect.arrayContaining(['--ci', '--config=./src/jest.config.js']), - { - silent: true - } - ) - }) + it('should call jest cli with configPath if configPath is passed in', async () => { + const jest = new Jest(logger, 'Jest', {}, { configPath: './src/jest.config.js' }) + await jest.run() + + expect(fork).toBeCalledWith( + expect.any(String), + expect.arrayContaining(['--config=./src/jest.config.js']), + { + silent: true + } + ) + }) - it('should call jest cli without configPath by default', async () => { - const jestCI = new JestCI(logger, 'JestCI', {}) - await jestCI.run() + it('should call jest cli with ci if ci is passed in', async () => { + const jest = new Jest(logger, 'Jest', {}, { ci: true }) + await jest.run() - expect(fork).toBeCalledWith( - expect.any(String), - expect.not.arrayContaining([expect.stringContaining('--config')]), - { silent: true } - ) + expect(fork).toBeCalledWith(expect.any(String), expect.arrayContaining(['--ci']), { + silent: true }) }) }) From a3ed567de658624b6e3bac4c938f2ae74f701a30 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:22:20 +0100 Subject: [PATCH 169/321] test(upload-assets-to-s3): fix tests for new task arg sig --- .../test/tasks/upload-assets-to-s3.test.ts | 86 +++++++++++++------ 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts index 098cb4a83..4259d678a 100644 --- a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts +++ b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts @@ -8,7 +8,7 @@ jest.mock('@aws-sdk/client-s3') const mockedS3Client = jest.mocked(S3Client, true) const mockedPutObjectCommand = jest.mocked(PutObjectCommand, true) -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger const testDirectory = path.join(__dirname, '../files') @@ -32,10 +32,15 @@ describe('upload-assets-to-s3', () => { }) it('should upload all globbed files for review', async () => { - const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { - ...defaults, - directory: testDirectory - }) + const task = new UploadAssetsToS3( + logger, + 'UploadAssetsToS3', + {}, + { + ...defaults, + directory: testDirectory + } + ) process.env.NODE_ENV = 'branch' await task.run() @@ -45,10 +50,15 @@ describe('upload-assets-to-s3', () => { }) it('should upload all globbed files for prod', async () => { - const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { - ...defaults, - directory: testDirectory - }) + const task = new UploadAssetsToS3( + logger, + 'UploadAssetsToS3', + {}, + { + ...defaults, + directory: testDirectory + } + ) process.env.NODE_ENV = 'production' await task.run() @@ -58,12 +68,17 @@ describe('upload-assets-to-s3', () => { }) it('should strip base path from S3 key', async () => { - const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { - ...defaults, - extensions: 'gz', - directory: testDirectory, - destination: 'testdir' - }) + const task = new UploadAssetsToS3( + logger, + 'UploadAssetsToS3', + {}, + { + ...defaults, + extensions: 'gz', + directory: testDirectory, + destination: 'testdir' + } + ) process.env.NODE_ENV = 'production' await task.run() @@ -73,11 +88,16 @@ describe('upload-assets-to-s3', () => { }) it('should use correct Content-Encoding for compressed files', async () => { - const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { - ...defaults, - extensions: 'gz', - directory: testDirectory - }) + const task = new UploadAssetsToS3( + logger, + 'UploadAssetsToS3', + {}, + { + ...defaults, + extensions: 'gz', + directory: testDirectory + } + ) process.env.NODE_ENV = 'production' await task.run() @@ -93,20 +113,30 @@ describe('upload-assets-to-s3', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any ;(mockedS3Client.prototype.send as any).mockRejectedValue(new Error(mockError)) - const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { - ...defaults, - directory: testDirectory - }) + const task = new UploadAssetsToS3( + logger, + 'UploadAssetsToS3', + {}, + { + ...defaults, + directory: testDirectory + } + ) await expect(task.run()).rejects.toThrow('ft-next-hashed-assets-prod failed') }) // HACK:20231006:IM make sure hack to support Doppler migration works it('should fallback to uppercase environment variable', async () => { - const task = new UploadAssetsToS3(logger, 'UploadAssestToS3', { - ...defaults, - directory: testDirectory - }) + const task = new UploadAssetsToS3( + logger, + 'UploadAssetsToS3', + {}, + { + ...defaults, + directory: testDirectory + } + ) // must use delete to ensure an environment variable is undefined, setting // 'undefined' will just stringify the word delete process.env.aws_access_hashed_assets From c2e682b0fa5a6ad102b1c1897690519abb980869 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:23:32 +0100 Subject: [PATCH 170/321] test(mocha): new arg signature --- plugins/mocha/test/tasks/mocha.test.ts | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/plugins/mocha/test/tasks/mocha.test.ts b/plugins/mocha/test/tasks/mocha.test.ts index 0096b535f..b97893ed4 100644 --- a/plugins/mocha/test/tasks/mocha.test.ts +++ b/plugins/mocha/test/tasks/mocha.test.ts @@ -5,21 +5,31 @@ import * as path from 'path' import Mocha from '../../src/tasks/mocha' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger describe('mocha', () => { it('should succeed with passing tests', async () => { - const task = new Mocha(logger, 'Mocha', { - files: path.resolve(__dirname, '../files/pass') + '/**/*.js' - }) + const task = new Mocha( + logger, + 'Mocha', + {}, + { + files: path.resolve(__dirname, '../files/pass') + '/**/*.js' + } + ) await task.run() }) it('should throw with failing tests', async () => { - const task = new Mocha(logger, 'Mocha', { - files: path.resolve(__dirname, '../files/fail') + '/**/*.js' - }) + const task = new Mocha( + logger, + 'Mocha', + {}, + { + files: path.resolve(__dirname, '../files/fail') + '/**/*.js' + } + ) expect.assertions(1) try { From e6cb8b1ec053db44831f21124f73d79c969bfd4d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:24:27 +0100 Subject: [PATCH 171/321] test(heroku): update tests for new options --- plugins/heroku/test/tasks/production.test.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/heroku/test/tasks/production.test.ts b/plugins/heroku/test/tasks/production.test.ts index 5765317fd..3e0d1a987 100644 --- a/plugins/heroku/test/tasks/production.test.ts +++ b/plugins/heroku/test/tasks/production.test.ts @@ -3,7 +3,7 @@ import Production from '../../src/tasks/production' import * as utils from '../../src/promoteStagingToProduction' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger jest.mock('@dotcom-tool-kit/state', () => { return { @@ -15,29 +15,32 @@ jest.mock('../../src/scaleDyno') const mockPromoteStagingToProduction = jest.spyOn(utils, 'promoteStagingToProduction') jest.spyOn(Production.prototype, 'fetchIfAppHasDeployed').mockImplementation(() => Promise.resolve(true)) -const productionOptions = { +const pluginOptions = { pipeline: 'next-health', - systemCode: 'next-health', + systemCode: 'next-health' +} + +const productionOptions = { scaling: { 'test-app': { web: { size: 'standard-1x', quantity: 1 } } } } describe('staging', () => { it('should call set slug with slug id and system code', async () => { mockPromoteStagingToProduction.mockImplementation(() => Promise.resolve([])) - const task = new Production(logger, 'HerokuProduction', productionOptions) + const task = new Production(logger, 'HerokuProduction', pluginOptions, productionOptions) await task.run() expect(utils.promoteStagingToProduction).toBeCalledWith(expect.anything(), 'slug-id', 'next-health') }) it('should resolve when completed successfully', async () => { - const task = new Production(logger, 'HerokuProduction', productionOptions) + const task = new Production(logger, 'HerokuProduction', pluginOptions, productionOptions) await expect(task.run()).resolves.not.toThrow() }) it('should throw if it completes unsuccessfully', async () => { mockPromoteStagingToProduction.mockImplementation(() => Promise.reject()) - const task = new Production(logger, 'HerokuProduction', productionOptions) + const task = new Production(logger, 'HerokuProduction', pluginOptions, productionOptions) await expect(task.run()).rejects.toThrowError() }) }) From 299a29aae0af3cf425c527705ac26dade05f59e5 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:36:43 +0100 Subject: [PATCH 172/321] test(prettier): update tests for new options --- .../fixtures/formatted-config-options.ts | 13 ---- .../prettier/test/files/fixtures/formatted.ts | 13 ---- plugins/prettier/test/tasks/prettier.test.ts | 67 ++++++------------- 3 files changed, 22 insertions(+), 71 deletions(-) delete mode 100644 plugins/prettier/test/files/fixtures/formatted-config-options.ts delete mode 100644 plugins/prettier/test/files/fixtures/formatted.ts diff --git a/plugins/prettier/test/files/fixtures/formatted-config-options.ts b/plugins/prettier/test/files/fixtures/formatted-config-options.ts deleted file mode 100644 index 5dc54f5aa..000000000 --- a/plugins/prettier/test/files/fixtures/formatted-config-options.ts +++ /dev/null @@ -1,13 +0,0 @@ -console.log({ - one: "one", - two: "two", - three: { - four: "four", - five: {}, - }, - six: "six", -}); - -console.log({ - hello: ["one", "two", "three"], -}); diff --git a/plugins/prettier/test/files/fixtures/formatted.ts b/plugins/prettier/test/files/fixtures/formatted.ts deleted file mode 100644 index aaeb339d6..000000000 --- a/plugins/prettier/test/files/fixtures/formatted.ts +++ /dev/null @@ -1,13 +0,0 @@ -console.log({ - one: 'one', - two: 'two', - three: { - four: 'four', - five: {} - }, - six: 'six' -}); - -console.log({ - hello: ['one', 'two', 'three'] -}); diff --git a/plugins/prettier/test/tasks/prettier.test.ts b/plugins/prettier/test/tasks/prettier.test.ts index 47ea310e5..28da6ca8f 100644 --- a/plugins/prettier/test/tasks/prettier.test.ts +++ b/plugins/prettier/test/tasks/prettier.test.ts @@ -4,23 +4,14 @@ import Prettier from '../../src/tasks/prettier' import { promises as fsp } from 'fs' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger const testDirectory = path.join(__dirname, '../files') -const defaultConfig = { - singleQuote: true, - useTabs: true, - bracketSpacing: true, - arrowParens: 'always', - trailingComma: 'none' -} - describe('prettier', () => { let unformattedFixture: string let formattedDefaultFixture: string let formattedConfigFileFixture: string - let formattedConfigOptionsFixture: string beforeAll(async () => { unformattedFixture = await fsp.readFile(path.join(testDirectory, './fixtures/unformatted.ts'), 'utf8') @@ -32,22 +23,22 @@ describe('prettier', () => { path.join(testDirectory, './fixtures/formatted-config-file.ts'), 'utf8' ) - formattedConfigOptionsFixture = await fsp.readFile( - path.join(testDirectory, './fixtures/formatted-config-options.ts'), - 'utf8' - ) }) beforeEach(async () => { await fsp.writeFile(path.join(testDirectory, 'unformatted.ts'), unformattedFixture) }) - it('should format the correct file with default configOptions', async () => { - const task = new Prettier(logger, 'Prettier', { - files: [path.join(testDirectory, 'unformatted.ts')], - ignoreFile: 'nonexistent prettierignore', - configOptions: defaultConfig - }) + it('should format the file with default options', async () => { + const task = new Prettier( + logger, + 'Prettier', + {}, + { + files: [path.join(testDirectory, 'unformatted.ts')], + ignoreFile: 'nonexistent prettierignore' + } + ) await task.run() const prettified = await fsp.readFile(path.join(testDirectory, 'unformatted.ts'), 'utf8') expect(prettified).toEqual(formattedDefaultFixture) @@ -55,33 +46,19 @@ describe('prettier', () => { it('should use configFile if present', async () => { // having the configuration file be named .prettierrc-test.json hides it from being found by prettier on other non-test occasions. - const task = new Prettier(logger, 'Prettier', { - files: [path.join(testDirectory, 'unformatted.ts')], - configFile: path.join(__dirname, '../.prettierrc-test.json'), - ignoreFile: 'nonexistent prettierignore', - configOptions: defaultConfig - }) - await task.run() - const prettified = await fsp.readFile(path.join(testDirectory, 'unformatted.ts'), 'utf8') - expect(prettified).toEqual(formattedConfigFileFixture) - }) - - it('should use configOptions if configFile not found', async () => { - const task = new Prettier(logger, 'Prettier', { - files: [path.join(testDirectory, 'unformatted.ts')], - configFile: '/incorrect/.prettierrc.js', - ignoreFile: 'nonexistent prettierignore', - configOptions: { - singleQuote: false, - useTabs: true, - bracketSpacing: false, - arrowParens: 'always', - trailingComma: 'all', - semi: true + const task = new Prettier( + logger, + 'Prettier', + {}, + { + files: [path.join(testDirectory, 'unformatted.ts')], + configFile: path.join(__dirname, '../.prettierrc-test.json'), + ignoreFile: 'nonexistent prettierignore' } - }) + ) + await task.run() const prettified = await fsp.readFile(path.join(testDirectory, 'unformatted.ts'), 'utf8') - expect(prettified).toEqual(formattedConfigOptionsFixture) + expect(prettified).toEqual(formattedConfigFileFixture) }) }) From 508460ffd73ad0a8fc4472b345494135bd35d440 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:39:01 +0100 Subject: [PATCH 173/321] test(cli): update tests for new task names --- .../files/conflict-resolution/.toolkitrc.yml | 20 ++++++++++--------- core/cli/test/files/duplicate/.toolkitrc.yml | 9 ++++++--- core/cli/test/index.test.ts | 7 ++----- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/core/cli/test/files/conflict-resolution/.toolkitrc.yml b/core/cli/test/files/conflict-resolution/.toolkitrc.yml index e0dd83e80..69eecfe01 100644 --- a/core/cli/test/files/conflict-resolution/.toolkitrc.yml +++ b/core/cli/test/files/conflict-resolution/.toolkitrc.yml @@ -9,24 +9,26 @@ options: '@dotcom-tool-kit/heroku': pipeline: tool-kit-test systemCode: tool-kit-test + '@dotcom-tool-kit/vault': + team: platforms + app: tool-kit-test + tasks: + HerokuProduction: scaling: tool-kit-test: web: size: standard-1x quantity: 1 - '@dotcom-tool-kit/vault': - team: platforms - app: tool-kit-test commands: build:local: - - WebpackDevelopment - - BabelDevelopment + - Webpack + - Babel build:ci: - - WebpackProduction - - BabelProduction + - Webpack + - Babel build:remote: - - WebpackProduction - - BabelProduction + - Webpack + - Babel version: 2 diff --git a/core/cli/test/files/duplicate/.toolkitrc.yml b/core/cli/test/files/duplicate/.toolkitrc.yml index 0bebeb564..15a2b4078 100644 --- a/core/cli/test/files/duplicate/.toolkitrc.yml +++ b/core/cli/test/files/duplicate/.toolkitrc.yml @@ -7,14 +7,17 @@ options: '@dotcom-tool-kit/heroku': pipeline: tool-kit-test systemCode: tool-kit-test + + '@dotcom-tool-kit/vault': + team: platforms + app: tool-kit-test + tasks: + HerokuProduction: scaling: tool-kit-test: web: size: standard-1x quantity: 1 - '@dotcom-tool-kit/vault': - team: platforms - app: tool-kit-test commands: diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index 5918de65d..24358ca62 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -9,7 +9,7 @@ import { createConfig, validateConfig } from '../src/config' import { loadPlugin, resolvePlugin } from '../src/plugin' import { validatePlugins } from '../src/config/validate-plugins' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger // Loading all the plugins can (unfortunately) take longer than the default 2s timeout jest.setTimeout(20000) @@ -105,10 +105,7 @@ describe('cli', () => { const validConfig = validateConfig(validPluginConfig, logger) expect(validConfig).not.toHaveProperty('commandTasks.build:local.conflicting') - expect(validConfig.commandTasks['build:local'].tasks).toEqual([ - 'WebpackDevelopment', - 'BabelDevelopment' - ]) + expect(validConfig.commandTasks['build:local'].tasks).toEqual(['Webpack', 'Babel']) } catch (e) { if (e instanceof ToolKitError) { e.message += '\n' + e.details From 59a9eb5d528ca630cb68b1aa6fd9882ed439594e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:39:37 +0100 Subject: [PATCH 174/321] test(n-test): update for new options --- plugins/n-test/test/tasks/n-test.test.ts | 37 +++++++++++++++++------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/plugins/n-test/test/tasks/n-test.test.ts b/plugins/n-test/test/tasks/n-test.test.ts index c448c2019..bc53128a1 100644 --- a/plugins/n-test/test/tasks/n-test.test.ts +++ b/plugins/n-test/test/tasks/n-test.test.ts @@ -5,7 +5,7 @@ import NTest from '../../src/tasks/n-test' import { writeState } from '@dotcom-tool-kit/state' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger const configAbsolutePath = path.join(__dirname, '../files/smoke.js') // n-test prepends the CWD to the given config path @@ -13,17 +13,27 @@ const configPath = path.relative('', configAbsolutePath) describe('n-test', () => { it('should pass when no errors', async () => { - const task = new NTest(logger, 'NTest', { - config: configPath - }) + const task = new NTest( + logger, + 'NTest', + {}, + { + config: configPath + } + ) await task.run() }) it('should fail when there are errors', async () => { - const task = new NTest(logger, 'NTest', { - config: configPath - }) + const task = new NTest( + logger, + 'NTest', + {}, + { + config: configPath + } + ) puppeteer.__setResponseStatus(404) @@ -38,14 +48,19 @@ describe('n-test', () => { it('should get app url from state', async () => { const appUrl = 'https://some-test-app.herokuapp.com' writeState('review', { url: appUrl }) - const task = new NTest(logger, 'NTest', { - config: configPath - }) + const task = new NTest( + logger, + 'NTest', + {}, + { + config: configPath + } + ) try { await task.run() } catch {} - expect(task.pluginOptions.host).toEqual(appUrl) + expect(task.options.host).toEqual(appUrl) }) }) From 764416177922a2d4d4fccbb7393bae86c5812d5b Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 9 Apr 2024 17:40:25 +0100 Subject: [PATCH 175/321] test(pa11y): update for new options --- plugins/pa11y/test/pa11y.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/pa11y/test/pa11y.test.ts b/plugins/pa11y/test/pa11y.test.ts index f65d6cded..9b9c8d5dd 100644 --- a/plugins/pa11y/test/pa11y.test.ts +++ b/plugins/pa11y/test/pa11y.test.ts @@ -5,7 +5,7 @@ import EventEmitter from 'events' import * as state from '@dotcom-tool-kit/state' const appName = 'test-app-name' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger jest.mock('child_process', () => ({ fork: jest.fn(() => { @@ -35,14 +35,14 @@ describe('pa11y', () => { }) it("sets process.env.TEST_URL as a herokuapp url if readState('review') is truthy", async () => { MOCK_ENV = 'ci' - const pa11y = new Pa11y(logger, 'Pa11y', {}) + const pa11y = new Pa11y(logger, 'Pa11y', {}, {}) await pa11y.run() expect(process.env.TEST_URL).toBe(`https://${appName}.herokuapp.com`) }) it("sets process.env.TEST_URL as a local env url if readState('local') is truthy", async () => { MOCK_ENV = 'local' - const pa11y = new Pa11y(logger, 'Pa11y', {}) + const pa11y = new Pa11y(logger, 'Pa11y', {}, {}) await pa11y.run() expect(process.env.TEST_URL).toBe(`https://local.ft.com:5050`) From 9a147c3feb26a0e095c4fcb46ca11f1b561848b3 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 10:47:31 +0100 Subject: [PATCH 176/321] test(upload-assets-to-s3): fix path to schema import --- .../upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts index 4259d678a..ec9f8ed9f 100644 --- a/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts +++ b/plugins/upload-assets-to-s3/test/tasks/upload-assets-to-s3.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach } from '@jest/globals' import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3' -import { UploadAssetsToS3Options } from '@dotcom-tool-kit/schemas/lib/plugins/upload-assets-to-s3' +import type { UploadAssetsToS3Options } from '@dotcom-tool-kit/schemas/lib/tasks/upload-assets-to-s3' import * as path from 'path' import winston, { Logger } from 'winston' import UploadAssetsToS3 from '../../src/tasks/upload-assets-to-s3' From afc8d54561bba42b133716c62e4b120dde27d8df Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 11:48:15 +0100 Subject: [PATCH 177/321] feat: explicitly handle legacy plugin options --- core/cli/src/plugin/options.ts | 22 +++++++++++++++++++++- lib/schemas/src/plugins.ts | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index 80bd05346..951d8b3e4 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -1,8 +1,10 @@ import { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { InvalidOption } from '../messages' -import { type PluginOptions, PluginSchemas } from '@dotcom-tool-kit/schemas' +import { type PluginOptions, PluginSchemas, legacyPluginOptions } from '@dotcom-tool-kit/schemas' import { isConflict } from '@dotcom-tool-kit/conflict' import type { Logger } from 'winston' +import { ZodError, ZodIssueCode } from 'zod' +import { styles } from '@dotcom-tool-kit/logger' export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig): InvalidOption[] => { const invalidOptions: InvalidOption[] = [] @@ -15,10 +17,28 @@ export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig } const pluginSchema = PluginSchemas[pluginId] + if (!pluginSchema) { logger.silly(`skipping validation of ${pluginId} plugin as no schema can be found`) + + // TODO:KB:20240412 remove legacyPluginOptions in a future major version + if (pluginOptions && pluginId in legacyPluginOptions) { + const movedToTask = legacyPluginOptions[pluginId] + invalidOptions.push([ + id, + new ZodError([ + { + message: `options for ${styles.plugin(id)} have moved to the ${styles.task(movedToTask)} task`, + code: ZodIssueCode.custom, + path: [] + } + ]) + ]) + } + continue } + const result = pluginSchema.safeParse(pluginOptions?.options ?? {}) if (result.success) { // Set up options entry for plugins that don't have options specified diff --git a/lib/schemas/src/plugins.ts b/lib/schemas/src/plugins.ts index fb669de6f..ad3f1ea26 100644 --- a/lib/schemas/src/plugins.ts +++ b/lib/schemas/src/plugins.ts @@ -1,3 +1,5 @@ +import { z } from 'zod' + import { CircleCISchema } from './plugins/circleci' import { DopplerSchema } from './plugins/doppler' import { RootSchema } from './plugins/dotcom-tool-kit' @@ -8,6 +10,23 @@ import { ServerlessSchema } from './plugins/serverless' import { VaultSchema } from './plugins/vault' import { type InferSchemaOptions } from './infer' +// TODO:KB:20240412 remove legacyPluginOptions in a future major version +export const legacyPluginOptions: Record = { + '@dotcom-tool-kit/babel': 'Babel', + '@dotcom-tool-kit/cypress': 'Cypress', + '@dotcom-tool-kit/eslint': 'ESLint', + '@dotcom-tool-kit/jest': 'Jest', + '@dotcom-tool-kit/mocha': 'Mocha', + '@dotcom-tool-kit/n-test': 'NTest', + '@dotcom-tool-kit/node': 'Node', + '@dotcom-tool-kit/nodemon': 'Nodemon', + '@dotcom-tool-kit/pa11y': 'Pa11y', + '@dotcom-tool-kit/prettier': 'Prettier', + '@dotcom-tool-kit/typescript': 'TypeScript', + '@dotcom-tool-kit/upload-assets-to-s3': 'UploadAssetsToS3', + '@dotcom-tool-kit/webpack': 'Webpack' +} + export const PluginSchemas = { 'app root': RootSchema, '@dotcom-tool-kit/circleci': CircleCISchema, From 5dd9ae48f95aee3f4113f7a83e8dce9f40241b2b Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 15:21:22 +0100 Subject: [PATCH 178/321] refactor: correct name and description for Webpack task Co-authored-by: Ivo Murrell --- plugins/webpack/src/tasks/webpack.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/webpack/src/tasks/webpack.ts b/plugins/webpack/src/tasks/webpack.ts index f0665a8d1..57c5d646b 100644 --- a/plugins/webpack/src/tasks/webpack.ts +++ b/plugins/webpack/src/tasks/webpack.ts @@ -5,8 +5,8 @@ import { fork } from 'child_process' const webpackCLIPath = require.resolve('webpack-cli/bin/cli') -export default class Babel extends Task<{ task: typeof WebpackSchema }> { - static description = 'build babel' +export default class Webpack extends Task<{ task: typeof WebpackSchema }> { + static description = 'build webpack' async run(): Promise { this.logger.info('starting Webpack...') From 655df3bb30a6e7b4c4365d0e5d9329b7acd7a2fe Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 15:22:20 +0100 Subject: [PATCH 179/321] refactor: use nullish coalescing instead of ternary for CYPRESS_BASE_URL Co-authored-by: Ivo Murrell --- plugins/cypress/src/tasks/cypress.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cypress/src/tasks/cypress.ts b/plugins/cypress/src/tasks/cypress.ts index 11b9b86d9..ec6aaf9d5 100644 --- a/plugins/cypress/src/tasks/cypress.ts +++ b/plugins/cypress/src/tasks/cypress.ts @@ -17,7 +17,7 @@ export default class Cypress extends Task<{ task: typeof CypressSchema }> { } if (appState) { - cypressEnv.CYPRESS_BASE_URL = appState.url ? appState.url : `https://${appState.appName}.herokuapp.com` + cypressEnv.CYPRESS_BASE_URL = appState.url ?? `https://${appState.appName}.herokuapp.com` if (reviewState) { cypressEnv.CYPRESS_REVIEW_APP = 'true' From 3b01211d021e3ec2ac75f5bd3996935019aa22b6 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 15:26:33 +0100 Subject: [PATCH 180/321] refactor: rename to ServerlessRunOptions for consistency Co-authored-by: Ivo Murrell --- lib/schemas/src/tasks/serverless-run.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/schemas/src/tasks/serverless-run.ts b/lib/schemas/src/tasks/serverless-run.ts index 872c26dcf..8c5892d24 100644 --- a/lib/schemas/src/tasks/serverless-run.ts +++ b/lib/schemas/src/tasks/serverless-run.ts @@ -5,6 +5,6 @@ export const ServerlessRunSchema = z.object({ useDoppler: z.boolean().default(true) }) -export type ServerlessOptions = z.infer +export type ServerlessRunOptions = z.infer export const Schema = ServerlessRunSchema From c63d92a67c778ddef06691c8adf00f0f81c8b4e2 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 15:28:02 +0100 Subject: [PATCH 181/321] chore: remove old TODO Co-authored-by: Ivo Murrell --- plugins/jest/src/tasks/jest.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/jest/src/tasks/jest.ts b/plugins/jest/src/tasks/jest.ts index 341274e22..e9040c7a5 100644 --- a/plugins/jest/src/tasks/jest.ts +++ b/plugins/jest/src/tasks/jest.ts @@ -35,8 +35,6 @@ export default class Jest extends Task<{ task: typeof JestSchema }> { async run(): Promise { const args = ['--colors', this.options.configPath ? `--config=${this.options.configPath}` : ''] - // TODO:20231107:IM we should probably refactor this plugin to move - // CI-specific logic to be within the CI task module if (this.options.ci) { args.push('--ci') // only relevant if running on CircleCI, other CI environments might handle From 85cce732a547607be848c927658203b294545b8e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 15:37:36 +0100 Subject: [PATCH 182/321] build: move dependency only used by eslint tests to eslint package --- package-lock.json | 4 ++-- package.json | 2 -- plugins/eslint/package.json | 2 ++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b32efdfc..ab7b21340 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,6 @@ "@tsconfig/node16": "^1.0.3", "@types/jest": "^27.4.0", "@types/node": "^16.18.23", - "@types/temp": "^0.9.4", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "check-engines": "^1.5.0", @@ -38,7 +37,6 @@ "lint-staged": "^10.5.4", "prettier": "^2.8.8", "release-please": "^15.0.0", - "temp": "^0.9.4", "ts-jest": "^27.1.3", "typescript": "~4.9.5" }, @@ -29550,7 +29548,9 @@ "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/eslint": "^7.2.13", + "@types/temp": "^0.9.4", "eslint": "^8.15.0", + "temp": "^0.9.4", "winston": "^3.5.1" }, "engines": { diff --git a/package.json b/package.json index df07278d2..4346725ad 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "@tsconfig/node16": "^1.0.3", "@types/jest": "^27.4.0", "@types/node": "^16.18.23", - "@types/temp": "^0.9.4", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "check-engines": "^1.5.0", @@ -39,7 +38,6 @@ "lint-staged": "^10.5.4", "prettier": "^2.8.8", "release-please": "^15.0.0", - "temp": "^0.9.4", "ts-jest": "^27.1.3", "typescript": "~4.9.5" }, diff --git a/plugins/eslint/package.json b/plugins/eslint/package.json index 9f3a7a367..755a1c5e7 100644 --- a/plugins/eslint/package.json +++ b/plugins/eslint/package.json @@ -26,7 +26,9 @@ "@dotcom-tool-kit/schemas": "^1.0.0", "@jest/globals": "^27.4.6", "@types/eslint": "^7.2.13", + "@types/temp": "^0.9.4", "eslint": "^8.15.0", + "temp": "^0.9.4", "winston": "^3.5.1" }, "files": [ From bb091c8d78ee8e71441c51da3f2e9a8d273ffeee Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 10 Apr 2024 09:19:03 +0100 Subject: [PATCH 183/321] feat: allow specifying command task options in a toolkitrc --- core/cli/src/config.ts | 8 +++---- core/cli/src/help.ts | 2 +- core/cli/src/messages.ts | 10 +++++---- core/cli/src/plugin/merge-commands.ts | 10 ++++++++- core/cli/src/tasks.ts | 31 ++++++++++++++------------- lib/plugin/src/index.ts | 9 +++++--- 6 files changed, 42 insertions(+), 28 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 0f380ef20..cd5ddf85e 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -57,7 +57,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali commandTaskConflicts.map((conflict) => ({ command: conflict.conflicting[0].id, conflictingTasks: conflict.conflicting.flatMap((command) => - command.tasks.map((task) => ({ task, plugin: command.plugin.id })) + command.tasks.map((task) => ({ task: task.name, plugin: command.plugin.id })) ) })) ) @@ -126,9 +126,9 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali const configuredCommandTasks = withoutConflicts(Object.values(config.commandTasks)) const missingTasks = configuredCommandTasks - .map((hook) => ({ - hook, - tasks: hook.tasks.filter((id) => !config.tasks[id]) + .map((command) => ({ + command, + tasks: command.tasks.filter((task) => !config.tasks[task.name]) })) .filter(({ tasks }) => tasks.length > 0) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index 0a7c23860..07b9b8028 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -50,7 +50,7 @@ ${(Hook.constructor as any).description ? (Hook.constructor as any).description ${ tasks && tasks.tasks.length ? `runs ${tasks.tasks.length > 1 ? 'these tasks' : 'this task'}: -${tasks.tasks.map((task) => `- ${styles.task(task)}`).join('\n')}` +${tasks.tasks.map((task) => `- ${styles.task(task.name)}`).join('\n')}` : styles.dim('no tasks configured to run on this hook.') } ${styles.ruler()} diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index b49d15534..0c739bf59 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -41,7 +41,9 @@ const formatCommandTaskConflict = (conflict: Conflict): string => ` ${conflict.conflicting .map( (command) => - `- ${command.tasks.map(s.task).join(s.dim(', '))} ${s.dim('by plugin')} ${s.plugin(command.plugin.id)}` + `- ${command.tasks.map((task) => s.task(task.name)).join(s.dim(', '))} ${s.dim('by plugin')} ${s.plugin( + command.plugin.id + )}` ) .join('\n')} ` @@ -147,11 +149,11 @@ ${uninstalledHooks.map((hook) => `- ${s.hook(hook.id || 'unknown event')}`).join Run ${s.task('dotcom-tool-kit --install')} to install these hooks. ` -type Missing = { hook: CommandTask; tasks: string[] } +type Missing = { command: CommandTask; tasks: { name: string; options: Record }[] } const formatMissingTask = (missing: Missing): string => - `- ${missing.tasks.map(s.task).join(', ')} ${s.dim( - `(assigned to ${s.hook(missing.hook.id)} by ${formatPlugin(missing.hook.plugin)})` + `- ${missing.tasks.map((task) => s.task(task.name)).join(', ')} ${s.dim( + `(assigned to ${s.hook(missing.command.id)} by ${formatPlugin(missing.command.plugin)})` )}` export const formatMissingTasks = ( diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts index 72715caa0..0053699bd 100644 --- a/core/cli/src/plugin/merge-commands.ts +++ b/core/cli/src/plugin/merge-commands.ts @@ -27,7 +27,15 @@ export const mergeCommands = (config: ValidPluginsConfig, plugin: Plugin, logger const newCommandTask: CommandTask = { id, plugin, - tasks: Array.isArray(configCommandTask) ? configCommandTask : [configCommandTask] + tasks: (Array.isArray(configCommandTask) ? configCommandTask : [configCommandTask]).flatMap( + (commandTask) => { + if (typeof commandTask === 'string') { + return [{ name: commandTask, options: {} }] + } + + return Object.entries(commandTask).map(([name, options]) => ({ name, options })) + } + ) } if (existingCommandTask) { diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 7fb795466..c74d491f3 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -19,25 +19,25 @@ type ErrorSummary = { const loadTasks = async ( logger: Logger, - taskNames: (keyof TaskOptions)[], + tasks: { name: string; options: Record }[], config: ValidConfig ): Promise>> => { const taskResults = await Promise.all( - taskNames.map(async (taskName) => { - const entryPoint = config.tasks[taskName] + tasks.map(async ({ name }) => { + const entryPoint = config.tasks[name] const taskResult = await importEntryPoint(Task, entryPoint) return taskResult.map((Task) => { - const taskSchema = TaskSchemas[taskName] - const parsedOptions = taskSchema ? taskSchema.parse(config.taskOptions[taskName]) : {} + const taskSchema = TaskSchemas[name as keyof TaskOptions] + const parsedOptions = taskSchema ? taskSchema.parse(config.taskOptions[name]) : {} const task = new (Task as unknown as TaskConstructor)( logger, - taskName, + name, getOptions(entryPoint.plugin.id as OptionKey) ?? {}, parsedOptions ) - return [taskName, task] + return [name, task] }) }) ) @@ -77,10 +77,9 @@ ${availableCommands}` process.execArgv.push('--no-experimental-fetch') } - const taskNames = commands.flatMap( - (command) => config.commandTasks[command]?.tasks ?? [] - ) as (keyof TaskOptions)[] - const tasks = (await loadTasks(logger, taskNames, config)).unwrap('tasks are invalid') + const commandTasks = commands.flatMap((command) => config.commandTasks[command]?.tasks ?? []) + + const tasks = (await loadTasks(logger, commandTasks, config)).unwrap('tasks are invalid') for (const command of commands) { const errors: ErrorSummary[] = [] @@ -90,15 +89,17 @@ ${availableCommands}` continue } - for (const id of config.commandTasks[command].tasks) { + for (const taskSpec of config.commandTasks[command].tasks) { + const taskId = typeof taskSpec === 'string' ? taskSpec : Object.keys(taskSpec)[0] + try { - logger.info(styles.taskHeader(`running ${styles.task(id)} task`)) - await tasks[id].run(files) + logger.info(styles.taskHeader(`running ${styles.task(taskId)} task`)) + await tasks[taskId].run(files) } catch (error) { // TODO use validated for this // allow subsequent command tasks to run on error errors.push({ - task: id, + task: taskId, error: error as Error }) } diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts index 696fc3c0a..cb604b577 100644 --- a/lib/plugin/src/index.ts +++ b/lib/plugin/src/index.ts @@ -1,3 +1,6 @@ +type TaskSpecWithOptions = Record> +type TaskSpec = string | TaskSpecWithOptions + export const CURRENT_RC_FILE_VERSION = 2 export type RCFile = { @@ -5,8 +8,8 @@ export type RCFile = { plugins: string[] installs: { [id: string]: string } tasks: { [id: string]: string } - commands: { [id: string]: string | string[] } - hooks?: { [id: string]: string | string[] } + commands: { [id: string]: TaskSpec | TaskSpec[] } + hooks?: { [id: string]: TaskSpec | TaskSpec[] } options: { plugins: { [id: string]: Record } tasks: { [id: string]: Record } @@ -26,7 +29,7 @@ export interface Plugin { export interface CommandTask { id: string plugin: Plugin - tasks: string[] + tasks: { name: string; options: Record }[] } export interface OptionsForPlugin { From 5a24e14bd12f93cb3f7b5d5da9ebb639a87699eb Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 11 Apr 2024 15:06:46 +0100 Subject: [PATCH 184/321] feat: merge in options from the command task when parsing task options --- core/cli/src/tasks.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index c74d491f3..3802d50a7 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -23,13 +23,13 @@ const loadTasks = async ( config: ValidConfig ): Promise>> => { const taskResults = await Promise.all( - tasks.map(async ({ name }) => { + tasks.map(async ({ name, options }) => { const entryPoint = config.tasks[name] const taskResult = await importEntryPoint(Task, entryPoint) return taskResult.map((Task) => { const taskSchema = TaskSchemas[name as keyof TaskOptions] - const parsedOptions = taskSchema ? taskSchema.parse(config.taskOptions[name]) : {} + const parsedOptions = taskSchema ? taskSchema.parse({ ...config.taskOptions[name], ...options }) : {} const task = new (Task as unknown as TaskConstructor)( logger, From 37da4d56c4cbe94fe047f1fdea6cd6515a96937f Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 11 Apr 2024 15:20:49 +0100 Subject: [PATCH 185/321] refactor: use the existing OptionsForTask type for command tasks --- core/cli/src/config.ts | 4 ++-- core/cli/src/help.ts | 2 +- core/cli/src/messages.ts | 6 +++--- core/cli/src/plugin/merge-commands.ts | 4 ++-- core/cli/src/tasks.ts | 21 +++++++++++---------- lib/plugin/src/index.ts | 2 +- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index cd5ddf85e..6ab36c5f1 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -57,7 +57,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali commandTaskConflicts.map((conflict) => ({ command: conflict.conflicting[0].id, conflictingTasks: conflict.conflicting.flatMap((command) => - command.tasks.map((task) => ({ task: task.name, plugin: command.plugin.id })) + command.tasks.map((task) => ({ task: task.task, plugin: command.plugin.id })) ) })) ) @@ -128,7 +128,7 @@ export function validateConfig(config: ValidPluginsConfig, logger: Logger): Vali const missingTasks = configuredCommandTasks .map((command) => ({ command, - tasks: command.tasks.filter((task) => !config.tasks[task.name]) + tasks: command.tasks.filter((task) => !config.tasks[task.task]) })) .filter(({ tasks }) => tasks.length > 0) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index 07b9b8028..dfcbaefe8 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -50,7 +50,7 @@ ${(Hook.constructor as any).description ? (Hook.constructor as any).description ${ tasks && tasks.tasks.length ? `runs ${tasks.tasks.length > 1 ? 'these tasks' : 'this task'}: -${tasks.tasks.map((task) => `- ${styles.task(task.name)}`).join('\n')}` +${tasks.tasks.map((task) => `- ${styles.task(task.task)}`).join('\n')}` : styles.dim('no tasks configured to run on this hook.') } ${styles.ruler()} diff --git a/core/cli/src/messages.ts b/core/cli/src/messages.ts index 0c739bf59..247c82a64 100644 --- a/core/cli/src/messages.ts +++ b/core/cli/src/messages.ts @@ -41,7 +41,7 @@ const formatCommandTaskConflict = (conflict: Conflict): string => ` ${conflict.conflicting .map( (command) => - `- ${command.tasks.map((task) => s.task(task.name)).join(s.dim(', '))} ${s.dim('by plugin')} ${s.plugin( + `- ${command.tasks.map((task) => s.task(task.task)).join(s.dim(', '))} ${s.dim('by plugin')} ${s.plugin( command.plugin.id )}` ) @@ -149,10 +149,10 @@ ${uninstalledHooks.map((hook) => `- ${s.hook(hook.id || 'unknown event')}`).join Run ${s.task('dotcom-tool-kit --install')} to install these hooks. ` -type Missing = { command: CommandTask; tasks: { name: string; options: Record }[] } +type Missing = { command: CommandTask; tasks: OptionsForTask[] } const formatMissingTask = (missing: Missing): string => - `- ${missing.tasks.map((task) => s.task(task.name)).join(', ')} ${s.dim( + `- ${missing.tasks.map((task) => s.task(task.task)).join(', ')} ${s.dim( `(assigned to ${s.hook(missing.command.id)} by ${formatPlugin(missing.command.plugin)})` )}` diff --git a/core/cli/src/plugin/merge-commands.ts b/core/cli/src/plugin/merge-commands.ts index 0053699bd..b16c0f89a 100644 --- a/core/cli/src/plugin/merge-commands.ts +++ b/core/cli/src/plugin/merge-commands.ts @@ -30,10 +30,10 @@ export const mergeCommands = (config: ValidPluginsConfig, plugin: Plugin, logger tasks: (Array.isArray(configCommandTask) ? configCommandTask : [configCommandTask]).flatMap( (commandTask) => { if (typeof commandTask === 'string') { - return [{ name: commandTask, options: {} }] + return [{ task: commandTask, options: {}, plugin }] } - return Object.entries(commandTask).map(([name, options]) => ({ name, options })) + return Object.entries(commandTask).map(([task, options]) => ({ task, options, plugin })) } ) } diff --git a/core/cli/src/tasks.ts b/core/cli/src/tasks.ts index 3802d50a7..4f6925cd3 100644 --- a/core/cli/src/tasks.ts +++ b/core/cli/src/tasks.ts @@ -11,6 +11,7 @@ import { styles } from '@dotcom-tool-kit/logger' import { shouldDisableNativeFetch } from './fetch' import { runInit } from './init' import { type TaskOptions, TaskSchemas } from '@dotcom-tool-kit/schemas' +import { OptionsForTask } from '@dotcom-tool-kit/plugin' type ErrorSummary = { task: string @@ -19,25 +20,27 @@ type ErrorSummary = { const loadTasks = async ( logger: Logger, - tasks: { name: string; options: Record }[], + tasks: OptionsForTask[], config: ValidConfig ): Promise>> => { const taskResults = await Promise.all( - tasks.map(async ({ name, options }) => { - const entryPoint = config.tasks[name] + tasks.map(async ({ task: taskId, options }) => { + const entryPoint = config.tasks[taskId] const taskResult = await importEntryPoint(Task, entryPoint) return taskResult.map((Task) => { - const taskSchema = TaskSchemas[name as keyof TaskOptions] - const parsedOptions = taskSchema ? taskSchema.parse({ ...config.taskOptions[name], ...options }) : {} + const taskSchema = TaskSchemas[taskId as keyof TaskOptions] + const parsedOptions = taskSchema + ? taskSchema.parse({ ...config.taskOptions[taskId].options, ...options }) + : {} const task = new (Task as unknown as TaskConstructor)( logger, - name, + taskId, getOptions(entryPoint.plugin.id as OptionKey) ?? {}, parsedOptions ) - return [name, task] + return [taskId, task] }) }) ) @@ -89,9 +92,7 @@ ${availableCommands}` continue } - for (const taskSpec of config.commandTasks[command].tasks) { - const taskId = typeof taskSpec === 'string' ? taskSpec : Object.keys(taskSpec)[0] - + for (const { task: taskId } of config.commandTasks[command].tasks) { try { logger.info(styles.taskHeader(`running ${styles.task(taskId)} task`)) await tasks[taskId].run(files) diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts index cb604b577..167da854e 100644 --- a/lib/plugin/src/index.ts +++ b/lib/plugin/src/index.ts @@ -29,7 +29,7 @@ export interface Plugin { export interface CommandTask { id: string plugin: Plugin - tasks: { name: string; options: Record }[] + tasks: OptionsForTask[] } export interface OptionsForPlugin { From ce91645c6fe873addb78f46003b91a407b041769 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 11 Apr 2024 15:22:48 +0100 Subject: [PATCH 186/321] test: fix tests looking for specific commandTasks structure --- core/cli/test/index.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index 24358ca62..dd551e7cd 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -105,7 +105,10 @@ describe('cli', () => { const validConfig = validateConfig(validPluginConfig, logger) expect(validConfig).not.toHaveProperty('commandTasks.build:local.conflicting') - expect(validConfig.commandTasks['build:local'].tasks).toEqual(['Webpack', 'Babel']) + expect(validConfig.commandTasks['build:local'].tasks.map((task) => task.task)).toEqual([ + 'Webpack', + 'Babel' + ]) } catch (e) { if (e instanceof ToolKitError) { e.message += '\n' + e.details From c5b63af05f6a7420498691966286a7059a046ff4 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 12 Apr 2024 11:04:22 +0100 Subject: [PATCH 187/321] feat: make ports optional in node and nodemon tasks --- lib/schemas/src/tasks/node.ts | 2 +- lib/schemas/src/tasks/nodemon.ts | 2 +- plugins/node/src/tasks/node.ts | 33 +++++++++++++++------------- plugins/nodemon/src/tasks/nodemon.ts | 14 +++++++----- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/lib/schemas/src/tasks/node.ts b/lib/schemas/src/tasks/node.ts index 287e0e52c..e0757b7a1 100644 --- a/lib/schemas/src/tasks/node.ts +++ b/lib/schemas/src/tasks/node.ts @@ -4,7 +4,7 @@ export const NodeSchema = z.object({ entry: z.string().default('./server/app.js'), args: z.string().array().optional(), useDoppler: z.boolean().default(true), - ports: z.number().array().default([3001, 3002, 3003]) + ports: z.union([z.number().array(), z.literal(false)]).default([3001, 3002, 3003]) }) export type NodeOptions = z.infer diff --git a/lib/schemas/src/tasks/nodemon.ts b/lib/schemas/src/tasks/nodemon.ts index 3f9151fc0..c79d2a26c 100644 --- a/lib/schemas/src/tasks/nodemon.ts +++ b/lib/schemas/src/tasks/nodemon.ts @@ -4,7 +4,7 @@ export const NodemonSchema = z.object({ entry: z.string().default('./server/app.js'), configPath: z.string().optional(), useDoppler: z.boolean().default(true), - ports: z.number().array().default([3001, 3002, 3003]) + ports: z.union([z.number().array(), z.literal(false)]).default([3001, 3002, 3003]) }) export type NodemonOptions = z.infer diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index 946e6cb1b..4a1e1621c 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -21,11 +21,12 @@ export default class Node extends Task<{ task: typeof NodeSchema }> { dopplerEnv = await doppler.get() } - const port = - Number(process.env.PORT) || - (await getPort({ - port: ports - })) + const port = ports + ? Number(process.env.PORT) || + (await getPort({ + port: ports + })) + : false this.logger.verbose('starting the child node process...') const child = fork(entry, args, { @@ -38,16 +39,18 @@ export default class Node extends Task<{ task: typeof NodeSchema }> { }) hookFork(this.logger, entry, child) - const unhook = hookConsole(this.logger, 'wait-port') - try { - await waitPort({ - host: 'localhost', - port: port - }) - } finally { - unhook() + if (port) { + const unhook = hookConsole(this.logger, 'wait-port') + try { + await waitPort({ + host: 'localhost', + port + }) + } finally { + unhook() + } + + writeState('local', { port }) } - - writeState('local', { port }) } } diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index 3dbfb2f78..7f97fd1c2 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -22,11 +22,12 @@ export default class Nodemon extends Task<{ task: typeof NodemonSchema }> { dopplerEnv = await doppler.get() } - const port = - Number(process.env.PORT) || - (await getPort({ - port: ports - })) + const port = ports + ? Number(process.env.PORT) || + (await getPort({ + port: ports + })) + : false this.logger.verbose('starting the child nodemon process...') @@ -68,6 +69,7 @@ export default class Nodemon extends Task<{ task: typeof NodemonSchema }> { nodemonLogger.log(nodemonToWinstonLogLevel(msg.type), msg.message + '\n') }) await new Promise((resolve) => nodemon.on('start', resolve)) - writeState('local', { port }) + + if (port) writeState('local', { port }) } } From e0e9b055decf3b0ca39caf49de7931f444b9f505 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 12:06:20 +0100 Subject: [PATCH 188/321] feat: add support for a managesFiles entry in hook installs fields --- core/cli/src/plugin/merge-hooks.ts | 4 ++-- lib/plugin/src/index.ts | 6 +++++- plugins/circleci/.toolkitrc.yml | 3 ++- plugins/package-json-hook/.toolkitrc.yml | 3 ++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/core/cli/src/plugin/merge-hooks.ts b/core/cli/src/plugin/merge-hooks.ts index eb1cd36db..b0d6b8da8 100644 --- a/core/cli/src/plugin/merge-hooks.ts +++ b/core/cli/src/plugin/merge-hooks.ts @@ -6,11 +6,11 @@ export const mergeHooks = (config: ValidPluginsConfig, plugin: Plugin) => { if (plugin.rcFile) { // add hooks to the registry, handling any conflicts // TODO refactor with command conflict handler - for (const [hookName, modulePath] of Object.entries(plugin.rcFile.installs || {})) { + for (const [hookName, hookSpec] of Object.entries(plugin.rcFile.installs || {})) { const existingHookId = config.hooks[hookName] const entryPoint: EntryPoint = { plugin, - modulePath + modulePath: hookSpec.entryPoint } if (existingHookId) { diff --git a/lib/plugin/src/index.ts b/lib/plugin/src/index.ts index 167da854e..9f3c55327 100644 --- a/lib/plugin/src/index.ts +++ b/lib/plugin/src/index.ts @@ -1,12 +1,16 @@ type TaskSpecWithOptions = Record> type TaskSpec = string | TaskSpecWithOptions +type InstallsSpec = { + entryPoint: string + managesFiles?: string[] +} export const CURRENT_RC_FILE_VERSION = 2 export type RCFile = { version?: typeof CURRENT_RC_FILE_VERSION plugins: string[] - installs: { [id: string]: string } + installs: { [id: string]: InstallsSpec } tasks: { [id: string]: string } commands: { [id: string]: TaskSpec | TaskSpec[] } hooks?: { [id: string]: TaskSpec | TaskSpec[] } diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index b96153b90..54120723f 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -1,5 +1,6 @@ installs: - CircleCi: './lib/circleci-config' + CircleCi: + entryPoint: './lib/circleci-config' options: hooks: diff --git a/plugins/package-json-hook/.toolkitrc.yml b/plugins/package-json-hook/.toolkitrc.yml index 2605e4902..41052ebb7 100644 --- a/plugins/package-json-hook/.toolkitrc.yml +++ b/plugins/package-json-hook/.toolkitrc.yml @@ -1,4 +1,5 @@ installs: - PackageJson: './lib/package-json-helper' + PackageJson: + entryPoint: './lib/package-json-helper' version: 2 From 731e55d3930f348a4e1f3b6da5b33b78ea65f89d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 12:08:44 +0100 Subject: [PATCH 189/321] feat: collect and store the hook-managed files in config --- core/cli/src/config.ts | 3 ++- core/cli/src/plugin/merge-hooks.ts | 1 + lib/config/src/index.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index 6ab36c5f1..db15d1663 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -35,7 +35,8 @@ export const createConfig = (): RawConfig => ({ pluginOptions: {}, taskOptions: {}, hooks: {}, - inits: [] + inits: [], + hookManagedFiles: new Set() }) export function validateConfig(config: ValidPluginsConfig, logger: Logger): ValidConfig { diff --git a/core/cli/src/plugin/merge-hooks.ts b/core/cli/src/plugin/merge-hooks.ts index b0d6b8da8..7579ef703 100644 --- a/core/cli/src/plugin/merge-hooks.ts +++ b/core/cli/src/plugin/merge-hooks.ts @@ -22,6 +22,7 @@ export const mergeHooks = (config: ValidPluginsConfig, plugin: Plugin) => { } } else { config.hooks[hookName] = entryPoint + hookSpec.managesFiles?.forEach((file) => config.hookManagedFiles.add(file)) } } } diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts index e82761b20..fe317aaa5 100644 --- a/lib/config/src/index.ts +++ b/lib/config/src/index.ts @@ -19,6 +19,7 @@ export interface RawConfig { taskOptions: { [id: string]: OptionsForTask | Conflict | undefined } hooks: { [id: string]: EntryPoint | Conflict } inits: EntryPoint[] + hookManagedFiles: Set } export type ValidPluginsConfig = Omit & { From 1159be17ffca3ab6a8a4fdf68be1b23d0e3e23aa Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 13:53:05 +0100 Subject: [PATCH 190/321] feat: read list of files to hash from config --- core/cli/src/config/hash.ts | 17 ++++++++++++----- core/cli/src/install.ts | 6 +++--- lib/state/src/index.ts | 3 +-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/core/cli/src/config/hash.ts b/core/cli/src/config/hash.ts index 9bbe21619..151f24d22 100644 --- a/core/cli/src/config/hash.ts +++ b/core/cli/src/config/hash.ts @@ -1,4 +1,5 @@ -import { configPaths, readState, writeState } from '@dotcom-tool-kit/state' +import { ValidConfig } from '@dotcom-tool-kit/config' +import { readState, writeState } from '@dotcom-tool-kit/state' import { createHash } from 'node:crypto' import { readFile } from 'node:fs/promises' import { Logger } from 'winston' @@ -17,20 +18,26 @@ export async function fileHash(path: string): Promise { } } -export async function updateHashes(): Promise { +export async function updateHashes(config: ValidConfig): Promise { const hashes = Object.fromEntries( - await Promise.all(configPaths.map(async (path) => [path, await fileHash(path)])) + await Promise.all( + ['.toolkitrc.yml', ...config.hookManagedFiles].map(async (path) => [path, await fileHash(path)]) + ) ) writeState('install', hashes) } -export async function hasConfigChanged(logger: Logger): Promise { +export async function hasConfigChanged(logger: Logger, config: ValidConfig): Promise { const hashes = readState('install') + if (!hashes) { return true } - for (const [path, prevHash] of Object.entries(hashes)) { + + for (const path of ['.toolkitrc.yml', ...config.hookManagedFiles]) { const newHash = await fileHash(path) + const prevHash = hashes[path] + if (newHash !== prevHash) { logger.debug(`hash for path ${path} has changed, running hook checks`) return true diff --git a/core/cli/src/install.ts b/core/cli/src/install.ts index 9ea0be94c..8613fd11c 100644 --- a/core/cli/src/install.ts +++ b/core/cli/src/install.ts @@ -79,7 +79,7 @@ export const loadHookInstallations = async ( } export async function checkInstall(logger: Logger, config: ValidConfig): Promise { - if (!(await hasConfigChanged(logger))) { + if (!(await hasConfigChanged(logger, config))) { return } @@ -95,7 +95,7 @@ export async function checkInstall(logger: Logger, config: ValidConfig): Promise throw error } - await updateHashes() + await updateHashes(config) } export default async function installHooks(logger: Logger): Promise { @@ -150,7 +150,7 @@ export default async function installHooks(logger: Logger): Promise throw error } - await updateHashes() + await updateHashes(config) return config } diff --git a/lib/state/src/index.ts b/lib/state/src/index.ts index 56657f09b..61c568a0c 100644 --- a/lib/state/src/index.ts +++ b/lib/state/src/index.ts @@ -4,8 +4,7 @@ import * as fs from 'fs' const target = process.env.INIT_CWD || process.cwd() const stateDir = target ? path.join(target, '.toolkitstate') : '.toolkitstate' -export const configPaths = ['.toolkitrc.yml', 'package.json', '.circleci/config.yml'] as const -type InstallState = Record<(typeof configPaths)[number], string> +type InstallState = Record interface CIState { repo: string From acf2e0805882d6a8fb63177b150795dc8b022712 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 16 Apr 2024 15:49:19 +0100 Subject: [PATCH 191/321] feat: add list of files that CircleCI and package.json hooks manage Co-authored-by: Ivo Murrell --- plugins/circleci/.toolkitrc.yml | 2 ++ plugins/package-json-hook/.toolkitrc.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index 54120723f..85714f2ef 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -1,6 +1,8 @@ installs: CircleCi: entryPoint: './lib/circleci-config' + managedFiles: + - '.circleci/config.yml' options: hooks: diff --git a/plugins/package-json-hook/.toolkitrc.yml b/plugins/package-json-hook/.toolkitrc.yml index 41052ebb7..4f2a43732 100644 --- a/plugins/package-json-hook/.toolkitrc.yml +++ b/plugins/package-json-hook/.toolkitrc.yml @@ -1,5 +1,7 @@ installs: PackageJson: entryPoint: './lib/package-json-helper' + managedFiles: + - 'package.json' version: 2 From e513389d4a60ed54b3562dc7c8aad23dae81431d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 18 Apr 2024 15:12:05 +0100 Subject: [PATCH 192/321] feat: overhaul help output for new abstractions & config structure --- core/cli/package.json | 1 + core/cli/src/help.ts | 118 ++++++++++++++--------- lib/logger/package.json | 1 + lib/logger/src/styles.ts | 21 +++- package-lock.json | 65 ++++++++++++- plugins/circleci/.toolkitrc.yml | 2 +- plugins/package-json-hook/.toolkitrc.yml | 2 +- 7 files changed, 159 insertions(+), 51 deletions(-) diff --git a/core/cli/package.json b/core/cli/package.json index b108b7b8c..80cf3990a 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -51,6 +51,7 @@ "@dotcom-tool-kit/validated": "^1.0.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "cosmiconfig": "^7.0.0", + "endent": "^2.1.0", "lodash": "^4.17.21", "minimist": "^1.2.5", "resolve-from": "^5.0.0", diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index dfcbaefe8..2aaf48a3e 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -1,13 +1,46 @@ import { loadConfig } from './config' import { OptionKey, setOptions } from '@dotcom-tool-kit/options' -import { styles } from '@dotcom-tool-kit/logger' +import { styles as s } from '@dotcom-tool-kit/logger' import type { Logger } from 'winston' +import YAML from 'yaml' +import $t from 'endent' +import { CommandTask, OptionsForTask } from '@dotcom-tool-kit/plugin' -export default async function showHelp(logger: Logger, hooks: string[]): Promise { +const toolKitIntro = s.box( + $t` + Tool Kit is modern, maintainable & modular developer tooling for FT.com projects. + ${s.URL('https://github.com/financial-times/dotcom-tool-kit')} + `, + { headerText: `🧰 ${s.title(`welcome to ${s.app('Tool Kit')}!`)}` } +) + +const formatTask = ({ task, options }: OptionsForTask) => $t` + ${s.task(task)}${ + Object.keys(options).length > 0 + ? ` ${s.dim('with options:')} + ${YAML.stringify(options).trim()}` + : '' +} +` + +const formatCommandTask = (command: string, { tasks, plugin }: CommandTask) => $t` + ${s.groupHeader(s.command(command))} + ${ + tasks.length + ? $t` + ${s.info(`${plugin.id !== 'app root' ? `from plugin ${s.plugin(plugin.id)}. ` : ''}runs tasks:`)} + ${tasks.map((task) => `- ${formatTask(task)}`).join('\n')} + ` + : s.warning('no tasks configured to run on this command') + } +` + +export default async function showHelp(logger: Logger, commands: string[]): Promise { const config = await loadConfig(logger) + const printAllCommands = commands.length === 0 - if (hooks.length === 0) { - hooks = Object.keys(config.hooks).sort() + if (printAllCommands) { + commands = Object.keys(config.commandTasks).sort() } for (const pluginOptions of Object.values(config.pluginOptions)) { @@ -16,52 +49,49 @@ export default async function showHelp(logger: Logger, hooks: string[]): Promise } } - const missingHooks = hooks.filter((hook) => !config.hooks[hook]) - - logger.info(` -🧰 ${styles.title(`welcome to ${styles.app('Tool Kit')}!`)} - -Tool Kit is modern, maintainable & modular developer tooling for FT.com projects. + logger.info($t` + ${toolKitIntro} + ${ + Object.keys(config.commandTasks).length === 0 + ? s.warning($t` + there are no commands available. add some commands by defining them in your ${s.filepath( + '.toolkitrc.yml' + )} or installing plugins that define commands. + `) + : '' + } + `) -${styles.URL('https://github.com/financial-times/dotcom-tool-kit')} + const missingCommands = commands.filter((command) => !config.commandTasks[command]) -${styles.ruler()} -${ - Object.keys(config.hooks).length === 0 - ? `there are no hooks available. you'll need to install plugins that define hooks to be able to run Tool Kit tasks.` - : styles.dim( - hooks.length === 0 - ? 'available hooks' - : `help for ${hooks.length - missingHooks.length} ${ - hooks.length - missingHooks.length > 1 ? 'hooks' : 'hook' - }` - ) -}: -`) + if (missingCommands.length) { + logger.warn( + s.warning($t` + no such ${missingCommands.length > 1 ? 'commands' : 'command'} ${missingCommands + .map(s.command) + .join(', ')} + `) + ) + } - for (const hook of hooks) { - const Hook = config.hooks[hook] + for (const command of commands) { + const commandTask = config.commandTasks[command] - if (Hook) { - const tasks = config.commandTasks[hook] - /* eslint-disable @typescript-eslint/no-explicit-any -- Object.constructor does not consider static properties */ - logger.info(`${styles.heading(hook)} -${(Hook.constructor as any).description ? (Hook.constructor as any).description + '\n' : ''} -${ - tasks && tasks.tasks.length - ? `runs ${tasks.tasks.length > 1 ? 'these tasks' : 'this task'}: -${tasks.tasks.map((task) => `- ${styles.task(task.task)}`).join('\n')}` - : styles.dim('no tasks configured to run on this hook.') -} -${styles.ruler()} -`) - /*eslint-enable @typescript-eslint/no-explicit-any */ + if (commandTask) { + logger.info(formatCommandTask(command, commandTask)) } } - if (missingHooks.length) { - logger.warn( - `no such ${missingHooks.length > 1 ? 'hooks' : 'hook'} ${missingHooks.map(styles.hook).join(', ')}` - ) + if (printAllCommands) { + for (const [hook, entryPoint] of Object.entries(config.hooks)) { + const managesFiles = entryPoint.plugin.rcFile?.installs[hook].managesFiles ?? [] + logger.info($t` + ${s.groupHeader(s.hook(hook))} + ${s.info($t` + from plugin ${s.plugin(entryPoint.plugin.id)}${managesFiles.length ? '. manages files:' : ''} + `)} + ${managesFiles.map((file) => `- ${s.filepath(file)}`).join('\n')} + `) + } } } diff --git a/lib/logger/package.json b/lib/logger/package.json index ec415425f..1df067876 100644 --- a/lib/logger/package.json +++ b/lib/logger/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", + "@visulima/boxen": "^1.0.6", "ansi-colors": "^4.1.1", "ansi-regex": "^5.0.1", "triple-beam": "^1.3.0", diff --git a/lib/logger/src/styles.ts b/lib/logger/src/styles.ts index 4f9bdbec1..4df8cd6ad 100644 --- a/lib/logger/src/styles.ts +++ b/lib/logger/src/styles.ts @@ -1,9 +1,13 @@ -import colours from 'ansi-colors' +import colours, { stripColor } from 'ansi-colors' +import { boxen } from '@visulima/boxen' + +type BoxenOptions = typeof boxen extends (text: string, options?: infer O) => string ? O : never // consistent styling use cases for terminal colours // don't use ansi-colors directly, define a style please export const styles = { - hook: colours.magenta, + hook: colours.yellow, + command: colours.magenta, task: colours.blueBright, plugin: colours.cyan, URL: colours.cyan.underline, @@ -20,5 +24,16 @@ export const styles = { error: (string: string): string => `${styles.errorHighlight.bold('‼︎')} ${styles.title(string)}`, warningHighlight: colours.yellow, warning: (string: string): string => styles.warningHighlight.bold('⚠︎') + ' ' + string, - ruler: (): string => styles.dim('─'.repeat(process.stdout.columns / 2)) + infoHighlight: colours.blue, + info: (string: string): string => styles.infoHighlight('ℹ︎') + ' ' + string, + ruler: (): string => styles.dim('─'.repeat(process.stdout.columns / 2)), + box: (string: string, options: Partial) => + boxen(string, { + borderStyle: 'round', + padding: { left: 1, right: 1 }, + ...options + }), + groupHeader: (string: string) => ` ╭─${'─'.repeat(stripColor(string).length)}─╮ +─┤ ${string} ├─${'─'.repeat(process.stdout.columns / 2 - stripColor(string).length - 6)} + ╰─${'─'.repeat(stripColor(string).length)}─╯` } diff --git a/package-lock.json b/package-lock.json index ab7b21340..43fe15e0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,6 +60,7 @@ "@dotcom-tool-kit/validated": "^1.0.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", "cosmiconfig": "^7.0.0", + "endent": "^2.1.0", "lodash": "^4.17.21", "minimist": "^1.2.5", "resolve-from": "^5.0.0", @@ -1262,6 +1263,7 @@ "license": "ISC", "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", + "@visulima/boxen": "^1.0.6", "ansi-colors": "^4.1.1", "ansi-regex": "^5.0.1", "triple-beam": "^1.3.0", @@ -10121,6 +10123,43 @@ "license": "ISC", "peer": true }, + "node_modules/@visulima/boxen": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@visulima/boxen/-/boxen-1.0.6.tgz", + "integrity": "sha512-Jn9+ddEn7scsEaU5/Yv6Kyf1pWIiFsj8vc1/s6mYTlQ16XX4k2j9yChBfT69a2X+AjefVHQJmbtjGbmOWD+bPg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/prisis" + }, + { + "type": "consulting", + "url": "https://anolilab.com/support" + } + ], + "os": [ + "darwin", + "linux", + "win32" + ], + "dependencies": { + "cli-boxes": "^3.0.0" + }, + "engines": { + "node": ">=18.* <=21.*" + } + }, + "node_modules/@visulima/boxen/node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@wdio/config": { "version": "5.22.4", "license": "MIT", @@ -11428,7 +11467,8 @@ }, "node_modules/boxen": { "version": "5.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", "peer": true, "dependencies": { "ansi-align": "^3.0.0", @@ -14097,6 +14137,16 @@ "once": "^1.4.0" } }, + "node_modules/endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dependencies": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, "node_modules/enhanced-resolve": { "version": "4.5.0", "dependencies": { @@ -15269,6 +15319,11 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-parse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "license": "MIT" @@ -21573,6 +21628,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/objectorarray": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==" + }, "node_modules/omggif": { "version": "1.0.10", "license": "MIT" @@ -29056,7 +29116,8 @@ }, "node_modules/yaml": { "version": "1.10.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "engines": { "node": ">= 6" } diff --git a/plugins/circleci/.toolkitrc.yml b/plugins/circleci/.toolkitrc.yml index 85714f2ef..ba83dabee 100644 --- a/plugins/circleci/.toolkitrc.yml +++ b/plugins/circleci/.toolkitrc.yml @@ -1,7 +1,7 @@ installs: CircleCi: entryPoint: './lib/circleci-config' - managedFiles: + managesFiles: - '.circleci/config.yml' options: diff --git a/plugins/package-json-hook/.toolkitrc.yml b/plugins/package-json-hook/.toolkitrc.yml index 4f2a43732..427f0b70c 100644 --- a/plugins/package-json-hook/.toolkitrc.yml +++ b/plugins/package-json-hook/.toolkitrc.yml @@ -1,7 +1,7 @@ installs: PackageJson: entryPoint: './lib/package-json-helper' - managedFiles: + managesFiles: - 'package.json' version: 2 From 72f0d2e1025c22a50c1010310f817206be32f4cb Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 18 Apr 2024 15:57:34 +0100 Subject: [PATCH 193/321] feat: better group --help output --- core/cli/src/help.ts | 91 +++++++++++++++++++++++++--------------- lib/logger/src/styles.ts | 6 +-- 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index 2aaf48a3e..0081279e0 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -5,6 +5,7 @@ import type { Logger } from 'winston' import YAML from 'yaml' import $t from 'endent' import { CommandTask, OptionsForTask } from '@dotcom-tool-kit/plugin' +import { ValidConfig } from '@dotcom-tool-kit/config' const toolKitIntro = s.box( $t` @@ -23,18 +24,58 @@ const formatTask = ({ task, options }: OptionsForTask) => $t` } ` +const formatCommandTasks = (config: ValidConfig, commands: string[]) => + s.box( + $t` + ${s.info( + `commands run Tool Kit tasks with ${s.code( + 'npx dotcom-tool-kit $command' + )}, or via configuration installed by hooks in your repository.` + )} + ${commands + .map((command) => + config.commandTasks[command] ? formatCommandTask(command, config.commandTasks[command]) + '\n' : '' + ) + .join('')} +`, + { + headerText: s.title('⚙️ available commands') + } + ) + const formatCommandTask = (command: string, { tasks, plugin }: CommandTask) => $t` ${s.groupHeader(s.command(command))} ${ tasks.length ? $t` ${s.info(`${plugin.id !== 'app root' ? `from plugin ${s.plugin(plugin.id)}. ` : ''}runs tasks:`)} - ${tasks.map((task) => `- ${formatTask(task)}`).join('\n')} + ${tasks.map((task) => ` - ${formatTask(task)}`).join('\n')} ` - : s.warning('no tasks configured to run on this command') + : s.warning(`no tasks configured to run for ${s.command(command)}`) } ` +const formatHooks = (config: ValidConfig) => + s.box( + $t` + ${s.info('hooks manage configuration files in your repository, for running Tool Kit commands.')} + ${Object.entries(config.hooks) + .map(([hook, entryPoint]) => { + const managesFiles = entryPoint.plugin.rcFile?.installs[hook].managesFiles ?? [] + return $t` + ${s.groupHeader(s.hook(hook))} + ${s.info($t` + from plugin ${s.plugin(entryPoint.plugin.id)} + `)} + ${managesFiles.length ? 'manages files:' : ''} + ${managesFiles.map((file) => ` - ${s.filepath(file)}`).join('\n')} + ` + }) + .join('\n')} +`, + { headerText: s.title('🎣 installed hooks') } + ) + export default async function showHelp(logger: Logger, commands: string[]): Promise { const config = await loadConfig(logger) const printAllCommands = commands.length === 0 @@ -49,21 +90,14 @@ export default async function showHelp(logger: Logger, commands: string[]): Prom } } - logger.info($t` - ${toolKitIntro} - ${ - Object.keys(config.commandTasks).length === 0 - ? s.warning($t` - there are no commands available. add some commands by defining them in your ${s.filepath( - '.toolkitrc.yml' - )} or installing plugins that define commands. - `) - : '' - } - `) + logger.info(toolKitIntro) const missingCommands = commands.filter((command) => !config.commandTasks[command]) + if (printAllCommands && Object.keys(config.hooks).length) { + logger.info(formatHooks(config)) + } + if (missingCommands.length) { logger.warn( s.warning($t` @@ -74,24 +108,15 @@ export default async function showHelp(logger: Logger, commands: string[]): Prom ) } - for (const command of commands) { - const commandTask = config.commandTasks[command] - - if (commandTask) { - logger.info(formatCommandTask(command, commandTask)) - } - } - - if (printAllCommands) { - for (const [hook, entryPoint] of Object.entries(config.hooks)) { - const managesFiles = entryPoint.plugin.rcFile?.installs[hook].managesFiles ?? [] - logger.info($t` - ${s.groupHeader(s.hook(hook))} - ${s.info($t` - from plugin ${s.plugin(entryPoint.plugin.id)}${managesFiles.length ? '. manages files:' : ''} - `)} - ${managesFiles.map((file) => `- ${s.filepath(file)}`).join('\n')} - `) + logger.info($t` + ${ + Object.keys(config.commandTasks).length === 0 + ? s.warning($t` + there are no commands available. add some commands by defining them in your ${s.filepath( + '.toolkitrc.yml' + )} or installing plugins that define commands. + `) + : formatCommandTasks(config, commands) } - } + `) } diff --git a/lib/logger/src/styles.ts b/lib/logger/src/styles.ts index 4df8cd6ad..1afe01e79 100644 --- a/lib/logger/src/styles.ts +++ b/lib/logger/src/styles.ts @@ -21,11 +21,11 @@ export const styles = { title: colours.bold.underline, taskHeader: colours.bgWhite.black, errorHighlight: colours.red, - error: (string: string): string => `${styles.errorHighlight.bold('‼︎')} ${styles.title(string)}`, + error: (string: string): string => `${styles.errorHighlight.bold('‼')} ${styles.title(string)}`, warningHighlight: colours.yellow, - warning: (string: string): string => styles.warningHighlight.bold('⚠︎') + ' ' + string, + warning: (string: string): string => styles.warningHighlight.bold('⚠') + ' ' + string, infoHighlight: colours.blue, - info: (string: string): string => styles.infoHighlight('ℹ︎') + ' ' + string, + info: (string: string): string => styles.infoHighlight('ℹ') + ' ' + string, ruler: (): string => styles.dim('─'.repeat(process.stdout.columns / 2)), box: (string: string, options: Partial) => boxen(string, { From 50736684687080074ec9d0f7082039e83d51d877 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 22 Apr 2024 14:31:24 +0100 Subject: [PATCH 194/321] feat: various help formatting and working tweaks idk --- core/cli/src/help.ts | 17 +++++++++-------- lib/logger/src/styles.ts | 23 +++++++++++++---------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index 0081279e0..347a0c614 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -21,14 +21,13 @@ const formatTask = ({ task, options }: OptionsForTask) => $t` ? ` ${s.dim('with options:')} ${YAML.stringify(options).trim()}` : '' -} -` +}` const formatCommandTasks = (config: ValidConfig, commands: string[]) => s.box( $t` - ${s.info( - `commands run Tool Kit tasks with ${s.code( + ${s.help( + `${s.command('commands')} run Tool Kit tasks with ${s.code( 'npx dotcom-tool-kit $command' )}, or via configuration installed by hooks in your repository.` )} @@ -39,7 +38,7 @@ const formatCommandTasks = (config: ValidConfig, commands: string[]) => .join('')} `, { - headerText: s.title('⚙️ available commands') + headerText: '⛭ ' + s.title('available commands') } ) @@ -58,7 +57,9 @@ const formatCommandTask = (command: string, { tasks, plugin }: CommandTask) => $ const formatHooks = (config: ValidConfig) => s.box( $t` - ${s.info('hooks manage configuration files in your repository, for running Tool Kit commands.')} + ${s.help( + `${s.hook('hooks')} manage configuration files in your repository, for running Tool Kit commands.` + )} ${Object.entries(config.hooks) .map(([hook, entryPoint]) => { const managesFiles = entryPoint.plugin.rcFile?.installs[hook].managesFiles ?? [] @@ -100,9 +101,9 @@ export default async function showHelp(logger: Logger, commands: string[]): Prom if (missingCommands.length) { logger.warn( - s.warning($t` + s.error($t` no such ${missingCommands.length > 1 ? 'commands' : 'command'} ${missingCommands - .map(s.command) + .map((id) => s.command(id)) .join(', ')} `) ) diff --git a/lib/logger/src/styles.ts b/lib/logger/src/styles.ts index 1afe01e79..7af18f652 100644 --- a/lib/logger/src/styles.ts +++ b/lib/logger/src/styles.ts @@ -1,4 +1,5 @@ -import colours, { stripColor } from 'ansi-colors' +import colours from 'chalk' +import stripAnsi from 'strip-ansi' import { boxen } from '@visulima/boxen' type BoxenOptions = typeof boxen extends (text: string, options?: infer O) => string ? O : never @@ -20,12 +21,14 @@ export const styles = { dim: colours.grey, title: colours.bold.underline, taskHeader: colours.bgWhite.black, - errorHighlight: colours.red, - error: (string: string): string => `${styles.errorHighlight.bold('‼')} ${styles.title(string)}`, - warningHighlight: colours.yellow, - warning: (string: string): string => styles.warningHighlight.bold('⚠') + ' ' + string, - infoHighlight: colours.blue, - info: (string: string): string => styles.infoHighlight('ℹ') + ' ' + string, + errorHighlight: colours.bgRed.bold, + error: (string: string): string => `${styles.errorHighlight(' × ️')} ${styles.title(string)}`, + warningHighlight: colours.bgYellow.bold, + warning: (string: string): string => styles.warningHighlight(' ! ') + ' ' + string, + infoHighlight: colours.bgBlueBright.bold, + info: (string: string): string => styles.infoHighlight(' i ') + ' ' + string, + helpHighlight: colours.bgGreen.bold, + help: (string: string): string => styles.helpHighlight(' ? ') + ' ' + string, ruler: (): string => styles.dim('─'.repeat(process.stdout.columns / 2)), box: (string: string, options: Partial) => boxen(string, { @@ -33,7 +36,7 @@ export const styles = { padding: { left: 1, right: 1 }, ...options }), - groupHeader: (string: string) => ` ╭─${'─'.repeat(stripColor(string).length)}─╮ -─┤ ${string} ├─${'─'.repeat(process.stdout.columns / 2 - stripColor(string).length - 6)} - ╰─${'─'.repeat(stripColor(string).length)}─╯` + groupHeader: (string: string) => ` ╭─${'─'.repeat(stripAnsi(string).length)}─╮ +─┤ ${string} ├─${'─'.repeat(process.stdout.columns / 2 - stripAnsi(string).length - 6)} + ╰─${'─'.repeat(stripAnsi(string).length)}─╯` } From 3d70ae19871078c35fcd11c63ef64bcb31cf133e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 22 Apr 2024 14:36:27 +0100 Subject: [PATCH 195/321] feat: better formatting for missing commands --- core/cli/src/help.ts | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index 347a0c614..ddf565743 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -99,6 +99,20 @@ export default async function showHelp(logger: Logger, commands: string[]): Prom logger.info(formatHooks(config)) } + if (missingCommands.length !== commands.length) { + logger.info($t` + ${ + Object.keys(config.commandTasks).length === 0 + ? s.warning($t` + there are no commands available. add some commands by defining them in your ${s.filepath( + '.toolkitrc.yml' + )} or installing plugins that define commands. + `) + : formatCommandTasks(config, commands) + } + `) + } + if (missingCommands.length) { logger.warn( s.error($t` @@ -109,15 +123,5 @@ export default async function showHelp(logger: Logger, commands: string[]): Prom ) } - logger.info($t` - ${ - Object.keys(config.commandTasks).length === 0 - ? s.warning($t` - there are no commands available. add some commands by defining them in your ${s.filepath( - '.toolkitrc.yml' - )} or installing plugins that define commands. - `) - : formatCommandTasks(config, commands) - } - `) + logger.info('\n') } From 033af0b36e961fd59a44bf819716643f33b7f82b Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 22 Apr 2024 14:49:14 +0100 Subject: [PATCH 196/321] fix: undefined commands logging --- core/cli/src/help.ts | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index ddf565743..a6f0121ce 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -93,27 +93,24 @@ export default async function showHelp(logger: Logger, commands: string[]): Prom logger.info(toolKitIntro) + const definedCommands = commands.filter((command) => config.commandTasks[command]) const missingCommands = commands.filter((command) => !config.commandTasks[command]) if (printAllCommands && Object.keys(config.hooks).length) { logger.info(formatHooks(config)) } - if (missingCommands.length !== commands.length) { - logger.info($t` - ${ - Object.keys(config.commandTasks).length === 0 - ? s.warning($t` - there are no commands available. add some commands by defining them in your ${s.filepath( - '.toolkitrc.yml' - )} or installing plugins that define commands. - `) - : formatCommandTasks(config, commands) - } - `) - } - - if (missingCommands.length) { + if (Object.keys(config.commandTasks).length === 0) { + logger.warn( + s.warning($t` + there are no commands available. add some commands by defining them in your ${s.filepath( + '.toolkitrc.yml' + )} or installing plugins that define commands. + `) + ) + } else if (definedCommands.length > 0) { + logger.info(formatCommandTasks(config, definedCommands)) + } else if (missingCommands.length) { logger.warn( s.error($t` no such ${missingCommands.length > 1 ? 'commands' : 'command'} ${missingCommands From 7812f570b94032bc2559eee1ae51e632ff71800e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 22 Apr 2024 16:48:56 +0100 Subject: [PATCH 197/321] fix: remove stray unicode variant selector in error mark Co-authored-by: Ivo Murrell --- lib/logger/src/styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/logger/src/styles.ts b/lib/logger/src/styles.ts index 7af18f652..e783d83e6 100644 --- a/lib/logger/src/styles.ts +++ b/lib/logger/src/styles.ts @@ -22,7 +22,7 @@ export const styles = { title: colours.bold.underline, taskHeader: colours.bgWhite.black, errorHighlight: colours.bgRed.bold, - error: (string: string): string => `${styles.errorHighlight(' × ️')} ${styles.title(string)}`, + error: (string: string): string => `${styles.errorHighlight(' × ')} ${styles.title(string)}`, warningHighlight: colours.bgYellow.bold, warning: (string: string): string => styles.warningHighlight(' ! ') + ' ' + string, infoHighlight: colours.bgBlueBright.bold, From 8217a73911bb1067c8c09c54ffe26c86eb83a0df Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 22 Apr 2024 16:50:30 +0100 Subject: [PATCH 198/321] refactor: use filter & map for formatCommandTasks Co-authored-by: Ivo Murrell --- core/cli/src/help.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index a6f0121ce..198d8258a 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -32,10 +32,10 @@ const formatCommandTasks = (config: ValidConfig, commands: string[]) => )}, or via configuration installed by hooks in your repository.` )} ${commands - .map((command) => - config.commandTasks[command] ? formatCommandTask(command, config.commandTasks[command]) + '\n' : '' - ) - .join('')} + .filter((command) => config.commandTasks[command]) + .map((command) => formatCommandTask(command, config.commandTasks[command])) + .join('\n')} + `, { headerText: '⛭ ' + s.title('available commands') From 9f03f9a8a91b93a90bd88551c5d307063f50e478 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 22 Apr 2024 16:55:42 +0100 Subject: [PATCH 199/321] fix: explicitly set error etc mark forgrounds to black for better contrast --- lib/logger/src/styles.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/logger/src/styles.ts b/lib/logger/src/styles.ts index e783d83e6..43f682ea3 100644 --- a/lib/logger/src/styles.ts +++ b/lib/logger/src/styles.ts @@ -21,13 +21,13 @@ export const styles = { dim: colours.grey, title: colours.bold.underline, taskHeader: colours.bgWhite.black, - errorHighlight: colours.bgRed.bold, + errorHighlight: colours.bgRed.black, error: (string: string): string => `${styles.errorHighlight(' × ')} ${styles.title(string)}`, - warningHighlight: colours.bgYellow.bold, + warningHighlight: colours.bgYellow.black, warning: (string: string): string => styles.warningHighlight(' ! ') + ' ' + string, - infoHighlight: colours.bgBlueBright.bold, + infoHighlight: colours.bgBlueBright.black, info: (string: string): string => styles.infoHighlight(' i ') + ' ' + string, - helpHighlight: colours.bgGreen.bold, + helpHighlight: colours.bgGreen.black, help: (string: string): string => styles.helpHighlight(' ? ') + ' ' + string, ruler: (): string => styles.dim('─'.repeat(process.stdout.columns / 2)), box: (string: string, options: Partial) => From 7ab1bb117a9f231126d7784f8f406c3673217fcb Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 22 Apr 2024 17:15:00 +0100 Subject: [PATCH 200/321] refactor: switch from fork to (an old version of) upstream boxen --- core/cli/src/help.ts | 6 ++--- lib/logger/package.json | 2 +- lib/logger/src/styles.ts | 8 +++--- package-lock.json | 54 +++++----------------------------------- 4 files changed, 13 insertions(+), 57 deletions(-) diff --git a/core/cli/src/help.ts b/core/cli/src/help.ts index 198d8258a..744bc8f2b 100644 --- a/core/cli/src/help.ts +++ b/core/cli/src/help.ts @@ -12,7 +12,7 @@ const toolKitIntro = s.box( Tool Kit is modern, maintainable & modular developer tooling for FT.com projects. ${s.URL('https://github.com/financial-times/dotcom-tool-kit')} `, - { headerText: `🧰 ${s.title(`welcome to ${s.app('Tool Kit')}!`)}` } + { title: `🧰 ${s.title(`welcome to ${s.app('Tool Kit')}!`)}` } ) const formatTask = ({ task, options }: OptionsForTask) => $t` @@ -38,7 +38,7 @@ const formatCommandTasks = (config: ValidConfig, commands: string[]) => `, { - headerText: '⛭ ' + s.title('available commands') + title: '⛭ ' + s.title('available commands') } ) @@ -74,7 +74,7 @@ const formatHooks = (config: ValidConfig) => }) .join('\n')} `, - { headerText: s.title('🎣 installed hooks') } + { title: s.title('🎣 installed hooks') } ) export default async function showHelp(logger: Logger, commands: string[]): Promise { diff --git a/lib/logger/package.json b/lib/logger/package.json index 1df067876..7ba374a70 100644 --- a/lib/logger/package.json +++ b/lib/logger/package.json @@ -24,9 +24,9 @@ }, "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", - "@visulima/boxen": "^1.0.6", "ansi-colors": "^4.1.1", "ansi-regex": "^5.0.1", + "boxen": "^5.1.2", "triple-beam": "^1.3.0", "tslib": "^2.3.1", "winston": "^3.5.1", diff --git a/lib/logger/src/styles.ts b/lib/logger/src/styles.ts index 43f682ea3..156c2aba5 100644 --- a/lib/logger/src/styles.ts +++ b/lib/logger/src/styles.ts @@ -1,8 +1,6 @@ import colours from 'chalk' import stripAnsi from 'strip-ansi' -import { boxen } from '@visulima/boxen' - -type BoxenOptions = typeof boxen extends (text: string, options?: infer O) => string ? O : never +import boxen from 'boxen' // consistent styling use cases for terminal colours // don't use ansi-colors directly, define a style please @@ -30,10 +28,10 @@ export const styles = { helpHighlight: colours.bgGreen.black, help: (string: string): string => styles.helpHighlight(' ? ') + ' ' + string, ruler: (): string => styles.dim('─'.repeat(process.stdout.columns / 2)), - box: (string: string, options: Partial) => + box: (string: string, options: Partial) => boxen(string, { borderStyle: 'round', - padding: { left: 1, right: 1 }, + padding: { top: 0, bottom: 0, left: 1, right: 1 }, ...options }), groupHeader: (string: string) => ` ╭─${'─'.repeat(stripAnsi(string).length)}─╮ diff --git a/package-lock.json b/package-lock.json index 43fe15e0d..dada7b334 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1091,11 +1091,11 @@ } }, "core/sandbox": { - "name": "@financial-times/sandbox", "version": "1.0.0", "license": "ISC", "dependencies": { "@dotcom-tool-kit/base": "file:../../lib/base", + "@dotcom-tool-kit/node": "file:../../plugins/node", "@dotcom-tool-kit/package-json-hook": "file:../../plugins/package-json-hook", "dotcom-tool-kit": "file:../cli" } @@ -1263,9 +1263,9 @@ "license": "ISC", "dependencies": { "@dotcom-tool-kit/error": "^3.2.0", - "@visulima/boxen": "^1.0.6", "ansi-colors": "^4.1.1", "ansi-regex": "^5.0.1", + "boxen": "^5.1.2", "triple-beam": "^1.3.0", "tslib": "^2.3.1", "winston": "^3.5.1", @@ -6639,10 +6639,6 @@ "version": "3.0.0", "license": "MIT" }, - "node_modules/@financial-times/sandbox": { - "resolved": "core/sandbox", - "link": true - }, "node_modules/@gar/promisify": { "version": "1.1.3", "license": "MIT" @@ -10123,43 +10119,6 @@ "license": "ISC", "peer": true }, - "node_modules/@visulima/boxen": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@visulima/boxen/-/boxen-1.0.6.tgz", - "integrity": "sha512-Jn9+ddEn7scsEaU5/Yv6Kyf1pWIiFsj8vc1/s6mYTlQ16XX4k2j9yChBfT69a2X+AjefVHQJmbtjGbmOWD+bPg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/prisis" - }, - { - "type": "consulting", - "url": "https://anolilab.com/support" - } - ], - "os": [ - "darwin", - "linux", - "win32" - ], - "dependencies": { - "cli-boxes": "^3.0.0" - }, - "engines": { - "node": ">=18.* <=21.*" - } - }, - "node_modules/@visulima/boxen/node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@wdio/config": { "version": "5.22.4", "license": "MIT", @@ -10584,7 +10543,6 @@ "node_modules/ansi-align": { "version": "3.0.1", "license": "ISC", - "peer": true, "dependencies": { "string-width": "^4.1.0" } @@ -11469,7 +11427,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "peer": true, "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -11490,7 +11447,6 @@ "node_modules/boxen/node_modules/camelcase": { "version": "6.3.0", "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -12167,7 +12123,6 @@ "node_modules/cli-boxes": { "version": "2.2.1", "license": "MIT", - "peer": true, "engines": { "node": ">=6" }, @@ -24468,6 +24423,10 @@ "version": "2.1.2", "license": "MIT" }, + "node_modules/sandbox": { + "resolved": "core/sandbox", + "link": true + }, "node_modules/sax": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", @@ -28869,7 +28828,6 @@ "node_modules/widest-line": { "version": "3.1.0", "license": "MIT", - "peer": true, "dependencies": { "string-width": "^4.0.0" }, From d08730a05ff110a742c961be5f7cb60ff16669c6 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 22 Apr 2024 18:14:34 +0100 Subject: [PATCH 201/321] fix: switch from upstream boxen to my fork --- lib/logger/package.json | 2 +- lib/logger/src/styles.ts | 2 +- package-lock.json | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/logger/package.json b/lib/logger/package.json index 7ba374a70..b6ca23b5d 100644 --- a/lib/logger/package.json +++ b/lib/logger/package.json @@ -23,10 +23,10 @@ "extends": "../../package.json" }, "dependencies": { + "@apaleslimghost/boxen": "^5.1.3", "@dotcom-tool-kit/error": "^3.2.0", "ansi-colors": "^4.1.1", "ansi-regex": "^5.0.1", - "boxen": "^5.1.2", "triple-beam": "^1.3.0", "tslib": "^2.3.1", "winston": "^3.5.1", diff --git a/lib/logger/src/styles.ts b/lib/logger/src/styles.ts index 156c2aba5..54dbd2f63 100644 --- a/lib/logger/src/styles.ts +++ b/lib/logger/src/styles.ts @@ -1,6 +1,6 @@ import colours from 'chalk' import stripAnsi from 'strip-ansi' -import boxen from 'boxen' +import boxen from '@apaleslimghost/boxen' // consistent styling use cases for terminal colours // don't use ansi-colors directly, define a style please diff --git a/package-lock.json b/package-lock.json index dada7b334..20e7dea78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1262,10 +1262,10 @@ "version": "3.4.0", "license": "ISC", "dependencies": { + "@apaleslimghost/boxen": "^5.1.3", "@dotcom-tool-kit/error": "^3.2.0", "ansi-colors": "^4.1.1", "ansi-regex": "^5.0.1", - "boxen": "^5.1.2", "triple-beam": "^1.3.0", "tslib": "^2.3.1", "winston": "^3.5.1", @@ -1520,6 +1520,38 @@ "node": ">=6.0.0" } }, + "node_modules/@apaleslimghost/boxen": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@apaleslimghost/boxen/-/boxen-5.1.3.tgz", + "integrity": "sha512-UkSSOihJUY2VKdU0WE8NH6xgB/P1iMEODkaXlRqCh5WDZ/8weZq/eHblFJM+F9CCd+QMkIbp2TjCmJB1A9rTRg==", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@apaleslimghost/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@aws-crypto/crc32": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", @@ -11427,6 +11459,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "peer": true, "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -11447,6 +11480,7 @@ "node_modules/boxen/node_modules/camelcase": { "version": "6.3.0", "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, From 2f658c4f169d97f76ff8c6dbbe1896fd2423262f Mon Sep 17 00:00:00 2001 From: Emilio de la Torre Date: Tue, 23 Apr 2024 16:24:36 +0100 Subject: [PATCH 202/321] feat(typescript): add support for typescript@5 as peer dependency --- plugins/typescript/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/typescript/package.json b/plugins/typescript/package.json index 955f8a75c..2ba1d42f0 100644 --- a/plugins/typescript/package.json +++ b/plugins/typescript/package.json @@ -22,7 +22,7 @@ ], "peerDependencies": { "dotcom-tool-kit": "3.x", - "typescript": "3.x || 4.x" + "typescript": "3.x || 4.x || 5.x" }, "dependencies": { "@dotcom-tool-kit/base": "^3.4.1", From 058b0ee3c35f76565b8bbdba3014ac7015f61f5c Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Fri, 19 Apr 2024 17:40:26 +0100 Subject: [PATCH 203/321] feat(cli)!: drop cosmiconfig and load .toolkitrc.yml at plugin's root cosmiconfig's magic handling of config files has long been a pain for us. It requires us to strategically place cache busting functions when we're rereading config files, and allows people to use many different kinds of configuration file formats, limiting our ability to extend YAML features. We've long assumed that people will just use a .toolkitrc.yml file for their config, and all our documentation recommends just that, so let's make it official. --- core/cli/package.json | 3 +-- core/cli/src/plugin.ts | 2 +- core/cli/src/rc-file.ts | 34 +++++++++++++--------------------- package-lock.json | 21 ++++++++++++++------- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/core/cli/package.json b/core/cli/package.json index 80cf3990a..fabdf77ba 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -50,14 +50,13 @@ "@dotcom-tool-kit/plugin": "^1.0.0", "@dotcom-tool-kit/validated": "^1.0.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", - "cosmiconfig": "^7.0.0", "endent": "^2.1.0", "lodash": "^4.17.21", "minimist": "^1.2.5", "resolve-from": "^5.0.0", "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", - "yaml": "^1.10.2", + "yaml": "^2.4.1", "zod-validation-error": "^2.1.0" }, "engines": { diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index 0b167bde4..f5d5c7669 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -37,7 +37,7 @@ export async function loadPlugin( id, root: pluginRoot, parent, - rcFile: await loadToolKitRC(logger, pluginRoot, isAppRoot), + rcFile: await loadToolKitRC(logger, pluginRoot), children: [] as Plugin[] } diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index b1fa2eec1..3e4430b32 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -1,10 +1,10 @@ +import fs from 'node:fs/promises' import { styles as s } from '@dotcom-tool-kit/logger' import type { RCFile } from '@dotcom-tool-kit/plugin' -import { cosmiconfig } from 'cosmiconfig' import * as path from 'path' import type { Logger } from 'winston' +import * as YAML from 'yaml' -export const explorer = cosmiconfig('toolkit', { ignoreEmptySearchPlaces: false }) const emptyConfig = { plugins: [], installs: {}, @@ -13,7 +13,6 @@ const emptyConfig = { options: { plugins: {}, tasks: {}, hooks: [] }, init: [] } satisfies RCFile -let rootConfig: string | undefined type RawRCFile = { [key in Exclude]?: RCFile[key] | null @@ -25,27 +24,20 @@ type RawRCFile = { | null } -export async function loadToolKitRC(logger: Logger, root: string, isAppRoot: boolean): Promise { - const result = await explorer.search(root) - if (!result?.config) { - return emptyConfig - } - if (isAppRoot) { - rootConfig = result.filepath - } else if (result.filepath === rootConfig) { - // Make sure that custom plugins which don't have a config file won't cause - // the resolver to use the root config instead and start an infinite loop - // of config resolution. - logger.warn( - `plugin at ${s.filepath(path.dirname(root))} has no config file. please add an empty ${s.filepath( - '.toolkitrc' - )} file to avoid potential config resolution issues.` - ) - return emptyConfig +export async function loadToolKitRC(logger: Logger, root: string): Promise { + let rawConfig: string + try { + rawConfig = await fs.readFile(path.join(root, '.toolkitrc.yml'), 'utf8') + } catch (err) { + if ((err as NodeJS.ErrnoException).code === 'ENOENT') { + return emptyConfig + } else { + throw err + } } - const config: RawRCFile = result.config + const config: RawRCFile = YAML.parse(rawConfig) // if a toolkitrc contains a non-empty options field, but not options.{plugins,tasks,hooks}, // assume it's an old-style, plugins-only options field. diff --git a/package-lock.json b/package-lock.json index 20e7dea78..e48773607 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,14 +59,13 @@ "@dotcom-tool-kit/plugin": "^1.0.0", "@dotcom-tool-kit/validated": "^1.0.0", "@dotcom-tool-kit/wait-for-ok": "^3.2.0", - "cosmiconfig": "^7.0.0", "endent": "^2.1.0", "lodash": "^4.17.21", "minimist": "^1.2.5", "resolve-from": "^5.0.0", "resolve-pkg": "^2.0.0", "tslib": "^2.3.1", - "yaml": "^1.10.2", + "yaml": "^2.4.1", "zod-validation-error": "^2.1.0" }, "bin": { @@ -127,6 +126,17 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, + "core/cli/node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "core/cli/node_modules/zod-validation-error": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-2.1.0.tgz", @@ -1092,6 +1102,7 @@ }, "core/sandbox": { "version": "1.0.0", + "extraneous": true, "license": "ISC", "dependencies": { "@dotcom-tool-kit/base": "file:../../lib/base", @@ -24457,10 +24468,6 @@ "version": "2.1.2", "license": "MIT" }, - "node_modules/sandbox": { - "resolved": "core/sandbox", - "link": true - }, "node_modules/sax": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", @@ -30747,7 +30754,7 @@ }, "peerDependencies": { "dotcom-tool-kit": "3.x", - "typescript": "3.x || 4.x" + "typescript": "3.x || 4.x || 5.x" } }, "plugins/typescript/node_modules/@babel/code-frame": { From e120891eb7b03633a8805da801374a196c128576 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Fri, 19 Apr 2024 17:44:44 +0100 Subject: [PATCH 204/321] fix(create): no longer need to clean cosmiconfig as we've dropped it --- core/create/package.json | 2 -- core/create/src/index.ts | 14 -------------- package-lock.json | 1 - 3 files changed, 17 deletions(-) diff --git a/core/create/package.json b/core/create/package.json index 4f47a11a2..c4de54b7b 100644 --- a/core/create/package.json +++ b/core/create/package.json @@ -16,7 +16,6 @@ "@dotcom-tool-kit/doppler": "^1.1.0", "@dotcom-tool-kit/error": "^3.2.0", "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/schemas": "^1.0.0", "@dotcom-tool-kit/plugin": "^1.0.0", "@dotcom-tool-kit/schemas": "^1.0.0", "@octokit/rest": "^19.0.5", @@ -53,7 +52,6 @@ "@types/node-fetch": "^2.6.2", "@types/pacote": "^11.1.3", "@types/prompts": "^2.0.14", - "cosmiconfig": "^7.0.1", "dotcom-tool-kit": "^3.4.5", "type-fest": "^3.13.1" }, diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 639414f20..a3787e9e1 100644 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -2,7 +2,6 @@ import * as ToolkitErrorModule from '@dotcom-tool-kit/error' import { rootLogger as winstonLogger, styles } from '@dotcom-tool-kit/logger' import type { RCFile } from '@dotcom-tool-kit/plugin' import { exec as _exec } from 'child_process' -import type { cosmiconfig } from 'cosmiconfig' import type { loadConfig as loadConfigType } from 'dotcom-tool-kit/lib/config' import fs, { promises as fsp } from 'fs' import importCwd from 'import-cwd' @@ -44,16 +43,6 @@ function getEslintConfigContent(): string { return eslintContentString } -function clearConfigCache() { - // we need to import explorer from the app itself instead of npx as this is - // the object used by installHooks() - return ( - importCwd('dotcom-tool-kit/lib/rc-file') as { - explorer: ReturnType - } - ).explorer.clearSearchCache() -} - async function executeMigration( deleteConfig: boolean, addEslintConfig: boolean, @@ -173,7 +162,6 @@ async function main() { if (optionsCancelled) { return } - clearConfigCache() try { await catchToolKitErrorsInLogger(logger, installHooks(winstonLogger), 'installing Tool Kit hooks', true) } catch (error) { @@ -189,14 +177,12 @@ async function main() { if (conflictsCancelled) { return } - clearConfigCache() await catchToolKitErrorsInLogger( logger, installHooks(winstonLogger), 'installing Tool Kit hooks again', false ) - clearConfigCache() } else { throw error } diff --git a/package-lock.json b/package-lock.json index e48773607..11cc36550 100644 --- a/package-lock.json +++ b/package-lock.json @@ -186,7 +186,6 @@ "@types/node-fetch": "^2.6.2", "@types/pacote": "^11.1.3", "@types/prompts": "^2.0.14", - "cosmiconfig": "^7.0.1", "dotcom-tool-kit": "^3.4.5", "type-fest": "^3.13.1" }, From e8cd1b8614fe3b92d583b3d093976c433b246e4b Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Fri, 19 Apr 2024 17:34:53 +0100 Subject: [PATCH 205/321] feat(cli): add support for tags in config that resolve based on options These two custom YAML tags allow us to define all the different combinations of Serverless and Cypress configuration needed to be added to CircleCI config. These were previously defined in JavaScript functions that were hard to compose but now they can be specified in a declarative, readable syntax along with the rest of the config. There are two tags available currently: `!toolkit/option` will substitute the specified option as a string into your config, whilst `!toolkit/defined` will conditionally include its value in your config if the specified option is defined. --- core/cli/src/config.ts | 14 ++++- core/cli/src/plugin.ts | 24 +++++++- core/cli/src/plugin/options.ts | 79 +++++++++++++++++++++++- core/cli/src/rc-file.ts | 39 +++++++++++- core/cli/test/index.test.ts | 6 +- core/cli/test/options.test.ts | 109 +++++++++++++++++++++++++++++++++ lib/config/src/index.ts | 6 +- 7 files changed, 266 insertions(+), 11 deletions(-) create mode 100644 core/cli/test/options.test.ts diff --git a/core/cli/src/config.ts b/core/cli/src/config.ts index db15d1663..894a492f1 100644 --- a/core/cli/src/config.ts +++ b/core/cli/src/config.ts @@ -1,7 +1,7 @@ import path from 'path' import type { Logger } from 'winston' -import { loadPlugin, resolvePlugin } from './plugin' +import { loadPlugin, resolvePlugin, resolvePluginOptions } from './plugin' import { findConflicts, withoutConflicts, @@ -22,14 +22,18 @@ import { formatUnusedTaskOptions } from './messages' import { validatePlugins } from './config/validate-plugins' -import { validatePluginOptions } from './plugin/options' +import { substituteOptionTags, validatePluginOptions } from './plugin/options' const coreRoot = path.resolve(__dirname, '../') export const createConfig = (): RawConfig => ({ root: coreRoot, plugins: {}, - resolvedPlugins: new Set(), + resolutionTrackers: { + resolvedPluginOptions: new Set(), + substitutedPlugins: new Set(), + resolvedPlugins: new Set() + }, tasks: {}, commandTasks: {}, pluginOptions: {}, @@ -159,6 +163,10 @@ export async function loadConfig(logger: Logger, { validate = true } = {}): Prom const validPluginConfig = validatedPluginConfig.unwrap('config was not valid!') // collate root plugin and descendent hooks, options etc into config + // start with options so we can substitute resolved values into other parts + // of the config + resolvePluginOptions(validRootPlugin, validPluginConfig) + substituteOptionTags(validRootPlugin, validPluginConfig) resolvePlugin(validRootPlugin, validPluginConfig, logger) return validate ? validateConfig(validPluginConfig, logger) : config diff --git a/core/cli/src/plugin.ts b/core/cli/src/plugin.ts index f5d5c7669..07d8308c8 100644 --- a/core/cli/src/plugin.ts +++ b/core/cli/src/plugin.ts @@ -71,10 +71,29 @@ export async function loadPlugin( }) } +export function resolvePluginOptions(plugin: Plugin, config: ValidPluginsConfig): void { + // don't resolve plugins that have already been resolved to prevent self-conflicts + // between plugins included at multiple points in the tree + if (config.resolutionTrackers.resolvedPluginOptions.has(plugin.id)) { + return + } + + if (plugin.children) { + // resolve child plugins first so parents can override the things their children set + for (const child of plugin.children) { + resolvePluginOptions(child, config) + } + } + + mergePluginOptions(config, plugin) + + config.resolutionTrackers.resolvedPluginOptions.add(plugin.id) +} + export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger: Logger): void { // don't resolve plugins that have already been resolved to prevent self-conflicts // between plugins included at multiple points in the tree - if (config.resolvedPlugins.has(plugin.id)) { + if (config.resolutionTrackers.resolvedPlugins.has(plugin.id)) { return } @@ -88,9 +107,8 @@ export function resolvePlugin(plugin: Plugin, config: ValidPluginsConfig, logger mergeTasks(config, plugin) mergeHooks(config, plugin) mergeCommands(config, plugin, logger) - mergePluginOptions(config, plugin) mergeTaskOptions(config, plugin) mergeInits(config, plugin) - config.resolvedPlugins.add(plugin.id) + config.resolutionTrackers.resolvedPlugins.add(plugin.id) } diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index 951d8b3e4..5f24de912 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -1,11 +1,16 @@ import { ValidPluginsConfig } from '@dotcom-tool-kit/config' -import { InvalidOption } from '../messages' -import { type PluginOptions, PluginSchemas, legacyPluginOptions } from '@dotcom-tool-kit/schemas' import { isConflict } from '@dotcom-tool-kit/conflict' +import { ToolKitError } from '@dotcom-tool-kit/error' +import { OptionsForPlugin, RCFile, type Plugin } from '@dotcom-tool-kit/plugin' +import { type PluginOptions, PluginSchemas, legacyPluginOptions } from '@dotcom-tool-kit/schemas' + import type { Logger } from 'winston' import { ZodError, ZodIssueCode } from 'zod' import { styles } from '@dotcom-tool-kit/logger' +import { toolKitIfDefinedIdent, toolKitOptionIdent } from '../rc-file' +import { InvalidOption } from '../messages' + export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig): InvalidOption[] => { const invalidOptions: InvalidOption[] = [] @@ -59,3 +64,73 @@ export const validatePluginOptions = (logger: Logger, config: ValidPluginsConfig return invalidOptions } + +export const substituteOptionTags = (plugin: Plugin, config: ValidPluginsConfig): void => { + // foo.bar gets the 'bar' option set for the 'foo' plugin + const resolveOptionPath = (optionPath: string): unknown => { + const [pluginName, optionName] = optionPath.split('.', 2) + return (config.pluginOptions[pluginName] as OptionsForPlugin)?.options[optionName] + } + + // throw an error if there are tags in plugin option fields to avoid circular + // references + const validateTagPath = (path: (string | number)[]) => { + if (path[0] === 'options' && path[1] === 'plugins') { + const error = new ToolKitError('cannot reference plugin options when specifying options') + error.details = `YAML tag referencing options used at path '${path.join('.')}'` + throw error + } + } + + // recursively walk through the parsed config, searching for the tag + // identifiers we've inserted during parsing, and substitute them for + // resolved option values + const deeplySubstitute = (node: unknown, path: (string | number)[]): unknown => { + if (Array.isArray(node)) { + return node.map((item, i) => deeplySubstitute(item, [...path, i])) + } else if (node && typeof node === 'object') { + const entries = Object.entries(node) + // !toolkit/option will be marked as a single entry within an object + // e.g., { foo: { '__toolkit/option__': 'foo.bar' } } + if (entries[0]?.[0] === toolKitOptionIdent) { + validateTagPath(path) + const optionPath = entries[0][1] as string + return resolveOptionPath(optionPath) + } else { + const substituted: Record = {} + for (const [key, value] of entries) { + if (key.startsWith(toolKitIfDefinedIdent)) { + validateTagPath(path) + // the option path is concatenated after the !toolkit/if-defined + // identifier + const optionPath = key.slice(toolKitIfDefinedIdent.length) + const optionValue = resolveOptionPath(optionPath) + if (optionValue) { + Object.assign(substituted, deeplySubstitute(value, path)) + } // don't include the node if !optionValue + } else { + substituted[key] = deeplySubstitute(value, [...path, key]) + } + } + return substituted + } + } else { + return node + } + } + + // avoid running substitution over a config repeatedly – all substitutions + // will have been made in the first pass + if (config.resolutionTrackers.substitutedPlugins.has(plugin.id)) { + return + } + if (plugin.children) { + for (const child of plugin.children) { + substituteOptionTags(child, config) + } + } + if (plugin.rcFile) { + plugin.rcFile = deeplySubstitute(plugin.rcFile, []) as RCFile + } + config.resolutionTrackers.substitutedPlugins.add(plugin.id) +} diff --git a/core/cli/src/rc-file.ts b/core/cli/src/rc-file.ts index 3e4430b32..e3838db10 100644 --- a/core/cli/src/rc-file.ts +++ b/core/cli/src/rc-file.ts @@ -14,6 +14,8 @@ const emptyConfig = { init: [] } satisfies RCFile +// TODO:IM:20240418 define another type that accounts for the custom tags +// existing deeply within the file type RawRCFile = { [key in Exclude]?: RCFile[key] | null } & { @@ -24,6 +26,28 @@ type RawRCFile = { | null } +// yaml will automatically stringify any symbols in keys so just use strings +// that won't be used normally +export const toolKitOptionIdent = '__toolkit/option__' +export const toolKitIfDefinedIdent = '__toolkit/if-defined__' + +// minimally define the two custom tags' identify callback so that yaml will +// parse them without warning but will never be use them when stringifying +const toolKitOption = { + identify: () => false, + tag: '!toolkit/option', + // wrap option path with identifier so we can substitute the option's value + // once it's been resolved later + resolve: (option) => ({ [toolKitOptionIdent]: option }) +} satisfies YAML.ScalarTag +const toolKitIfDefined = { + identify: () => false, + tag: '!toolkit/if-defined', + // the resolve callback doesn't allow us to manipulate the whole YAML.Pair + // with this tagged key, so just return it unchanged now and find the tag in + // a YAML.visit later + resolve: (value) => value +} satisfies YAML.ScalarTag export async function loadToolKitRC(logger: Logger, root: string): Promise { let rawConfig: string @@ -37,7 +61,20 @@ export async function loadToolKitRC(logger: Logger, root: string): Promise { expect(validatedPluginConfig.valid).toBe(true) const validPluginConfig = (validatedPluginConfig as Valid).value + resolvePluginOptions((plugin as Valid).value, validPluginConfig) resolvePlugin((plugin as Valid).value, validPluginConfig, logger) expect(() => validateConfig(validPluginConfig, logger)).toThrow(ToolKitError) @@ -51,6 +52,7 @@ describe('cli', () => { expect(validatedPluginConfig.valid).toBe(true) const validPluginConfig = (validatedPluginConfig as Valid).value + resolvePluginOptions((plugin as Valid).value, validPluginConfig) resolvePlugin((plugin as Valid).value, validPluginConfig, logger) expect(() => validateConfig(validPluginConfig, logger)).toThrow(ToolKitError) @@ -72,6 +74,7 @@ describe('cli', () => { expect(validatedPluginConfig.valid).toBe(true) const validPluginConfig = (validatedPluginConfig as Valid).value + resolvePluginOptions((plugin as Valid).value, validPluginConfig) resolvePlugin((plugin as Valid).value, validPluginConfig, logger) try { @@ -99,6 +102,7 @@ describe('cli', () => { expect(validatedPluginConfig.valid).toBe(true) const validPluginConfig = (validatedPluginConfig as Valid).value + resolvePluginOptions((plugin as Valid).value, validPluginConfig) resolvePlugin((plugin as Valid).value, validPluginConfig, logger) try { diff --git a/core/cli/test/options.test.ts b/core/cli/test/options.test.ts new file mode 100644 index 000000000..d8652a55d --- /dev/null +++ b/core/cli/test/options.test.ts @@ -0,0 +1,109 @@ +import { loadConfig } from '../src/config' + +import * as fs from 'node:fs/promises' + +import type { Valid } from '@dotcom-tool-kit/validated' +import type { Plugin } from '@dotcom-tool-kit/plugin' + +import winston, { type Logger } from 'winston' + +const logger = winston as unknown as Logger + +jest.mock('node:fs/promises') +const mockedFs = jest.mocked(fs) + +// convince text editors (well, nvim) to highlight strings as YAML +const yaml = (str) => str + +describe('option substitution', () => { + it('should substitute option tag with option value', async () => { + mockedFs.readFile.mockResolvedValueOnce( + yaml(` +options: + plugins: + test: + foo: bar + hooks: + - Test: + baz: !toolkit/option 'test.foo' +`) + ) + + const config = await loadConfig(logger, { validate: false }) + const plugin = config.plugins['app root'] + expect(plugin.valid).toBe(true) + expect((plugin as Valid).value.rcFile?.options.hooks[0].Test.baz).toEqual('bar') + }) + + it('should substitute defined tag with value when defined', async () => { + mockedFs.readFile.mockResolvedValueOnce( + yaml(` +options: + plugins: + test: + foo: bar + hooks: + - Test: + !toolkit/if-defined 'test.foo': + hello: world +`) + ) + + const config = await loadConfig(logger, { validate: false }) + const plugin = config.plugins['app root'] + expect(plugin.valid).toBe(true) + expect((plugin as Valid).value.rcFile?.options.hooks[0].Test.hello).toEqual('world') + }) + + it('should delete defined tag when not defined', async () => { + mockedFs.readFile.mockResolvedValueOnce( + yaml(` +options: + hooks: + - Test: + !toolkit/if-defined 'test.foo': + hello: world +`) + ) + + const config = await loadConfig(logger, { validate: false }) + const plugin = config.plugins['app root'] + expect(plugin.valid).toBe(true) + expect((plugin as Valid).value.rcFile?.options.hooks[0].Test.hello).toBeUndefined() + }) + + it('should support nested tags', async () => { + mockedFs.readFile.mockResolvedValueOnce( + yaml(` +options: + plugins: + test: + foo: bar + hooks: + - Test: + !toolkit/if-defined 'test.foo': + hello: !toolkit/option 'test.foo' +`) + ) + + const config = await loadConfig(logger, { validate: false }) + const plugin = config.plugins['app root'] + expect(plugin.valid).toBe(true) + expect((plugin as Valid).value.rcFile?.options.hooks[0].Test.hello).toEqual('bar') + }) + + it('should disallow tags within plugin options', async () => { + mockedFs.readFile.mockResolvedValueOnce( + yaml(` +options: + plugins: + test: + foo: !toolkit/option 'test.foo' +`) + ) + + expect(loadConfig(logger, { validate: false })).rejects.toThrowErrorMatchingInlineSnapshot( + `"cannot reference plugin options when specifying options"` + ) + }) +}) diff --git a/lib/config/src/index.ts b/lib/config/src/index.ts index fe317aaa5..053d04faa 100644 --- a/lib/config/src/index.ts +++ b/lib/config/src/index.ts @@ -12,7 +12,11 @@ import type { Conflict } from '@dotcom-tool-kit/conflict' export interface RawConfig { root: string plugins: { [id: string]: Validated } - resolvedPlugins: Set + resolutionTrackers: { + resolvedPluginOptions: Set + substitutedPlugins: Set + resolvedPlugins: Set + } tasks: { [id: string]: EntryPoint | Conflict } commandTasks: { [id: string]: CommandTask | Conflict } pluginOptions: { [id: string]: OptionsForPlugin | Conflict | undefined } From b0585c3ac17474454af9796822b50f36c3b0f793 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Thu, 18 Apr 2024 17:10:58 +0100 Subject: [PATCH 206/321] feat(circleci-deploy): define Cypress and Serverless options with tags --- plugins/circleci-deploy/.toolkitrc.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/plugins/circleci-deploy/.toolkitrc.yml b/plugins/circleci-deploy/.toolkitrc.yml index f7eebc84e..a3bf94d7c 100644 --- a/plugins/circleci-deploy/.toolkitrc.yml +++ b/plugins/circleci-deploy/.toolkitrc.yml @@ -40,11 +40,20 @@ options: - 'deploy-review' splitIntoMatrix: false custom: + !toolkit/if-defined '@dotcom-tool-kit/circleci.cypressImage': + executor: cypress + !toolkit/if-defined '@dotcom-tool-kit/serverless.awsAccountId': + aws-account-id: !toolkit/option '@dotcom-tool-kit/serverless.awsAccountId' + system-code: !toolkit/option '@dotcom-tool-kit/serverless.systemCode' + !toolkit/if-defined '@dotcom-tool-kit/next-router.appName': + appName: !toolkit/option '@dotcom-tool-kit/next-router.appName' - name: 'e2e-test-staging' splitIntoMatrix: false requires: - 'deploy-staging' custom: + !toolkit/if-defined '@dotcom-tool-kit/circleci.cypressImage': + executor: cypress - name: 'deploy-production' requires: - 'test' @@ -54,6 +63,9 @@ options: filters: branches: only: main + !toolkit/if-defined '@dotcom-tool-kit/serverless.awsAccountId': + aws-account-id: !toolkit/option '@dotcom-tool-kit/serverless.awsAccountId' + system-code: !toolkit/option '@dotcom-tool-kit/serverless.systemCode' - name: 'nightly' jobs: - name: 'deploy-review' @@ -65,5 +77,12 @@ options: filters: branches: ignore: main + !toolkit/if-defined '@dotcom-tool-kit/serverless.awsAccountId': + aws-account-id: !toolkit/option '@dotcom-tool-kit/serverless.awsAccountId' + system-code: !toolkit/option '@dotcom-tool-kit/serverless.systemCode' + !toolkit/if-defined '@dotcom-tool-kit/circleci.cypressImage': + executors: + - name: cypress + image: !toolkit/option '@dotcom-tool-kit/circleci.cypressImage' version: 2 From 78eed8e77555727becf71ca64009b384224f151b Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Tue, 23 Apr 2024 17:12:00 +0100 Subject: [PATCH 207/321] feat(cli): gather all YAML tag errors into Validated before throwing This will prevent users having to play 'whackamole' when fixing all their misplaced tags. --- core/cli/src/plugin/options.ts | 56 ++++++++++++++++++++++------------ core/cli/test/options.test.ts | 28 +++++++++++++++++ 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/core/cli/src/plugin/options.ts b/core/cli/src/plugin/options.ts index 5f24de912..05166896d 100644 --- a/core/cli/src/plugin/options.ts +++ b/core/cli/src/plugin/options.ts @@ -1,8 +1,8 @@ import { ValidPluginsConfig } from '@dotcom-tool-kit/config' import { isConflict } from '@dotcom-tool-kit/conflict' -import { ToolKitError } from '@dotcom-tool-kit/error' import { OptionsForPlugin, RCFile, type Plugin } from '@dotcom-tool-kit/plugin' import { type PluginOptions, PluginSchemas, legacyPluginOptions } from '@dotcom-tool-kit/schemas' +import { invalid, reduceValidated, valid, Validated } from '@dotcom-tool-kit/validated' import type { Logger } from 'winston' import { ZodError, ZodIssueCode } from 'zod' @@ -74,48 +74,64 @@ export const substituteOptionTags = (plugin: Plugin, config: ValidPluginsConfig) // throw an error if there are tags in plugin option fields to avoid circular // references - const validateTagPath = (path: (string | number)[]) => { + const validateTagPath = (path: (string | number)[]): string | void => { if (path[0] === 'options' && path[1] === 'plugins') { - const error = new ToolKitError('cannot reference plugin options when specifying options') - error.details = `YAML tag referencing options used at path '${path.join('.')}'` - throw error + return `YAML tag referencing options used at path '${path.join('.')}'` } } // recursively walk through the parsed config, searching for the tag // identifiers we've inserted during parsing, and substitute them for // resolved option values - const deeplySubstitute = (node: unknown, path: (string | number)[]): unknown => { + const deeplySubstitute = (node: unknown, path: (string | number)[]): Validated => { if (Array.isArray(node)) { - return node.map((item, i) => deeplySubstitute(item, [...path, i])) + return reduceValidated(node.map((item, i) => deeplySubstitute(item, [...path, i]))) } else if (node && typeof node === 'object') { const entries = Object.entries(node) // !toolkit/option will be marked as a single entry within an object // e.g., { foo: { '__toolkit/option__': 'foo.bar' } } if (entries[0]?.[0] === toolKitOptionIdent) { - validateTagPath(path) - const optionPath = entries[0][1] as string - return resolveOptionPath(optionPath) + const validationError = validateTagPath(path) + if (validationError) { + return invalid([validationError]) + } else { + const optionPath = entries[0][1] as string + return valid(resolveOptionPath(optionPath)) + } } else { - const substituted: Record = {} + const substituted: Validated<[string, unknown]>[] = [] for (const [key, value] of entries) { if (key.startsWith(toolKitIfDefinedIdent)) { - validateTagPath(path) + const validationError = validateTagPath(path) + if (validationError) { + substituted.push(invalid([validationError])) + } // the option path is concatenated after the !toolkit/if-defined // identifier const optionPath = key.slice(toolKitIfDefinedIdent.length) const optionValue = resolveOptionPath(optionPath) - if (optionValue) { - Object.assign(substituted, deeplySubstitute(value, path)) - } // don't include the node if !optionValue + // keep walking the path if we've found an error here so we can + // gather even more errors to show the user. else skip traversal if + // we aren't going to include the node + if (optionValue || validationError) { + const subbedValues = deeplySubstitute(value, path) + if (subbedValues.valid) { + substituted.push(...Object.entries(subbedValues.value as object).map((v) => valid(v))) + } else { + /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- + * Invalid objects don't need to match the inner type + **/ + substituted.push(subbedValues as Validated) + } + } } else { - substituted[key] = deeplySubstitute(value, [...path, key]) + substituted.push(deeplySubstitute(value, [...path, key]).map((subbedValue) => [key, subbedValue])) } } - return substituted + return reduceValidated(substituted).map(Object.fromEntries) } } else { - return node + return valid(node) } } @@ -130,7 +146,9 @@ export const substituteOptionTags = (plugin: Plugin, config: ValidPluginsConfig) } } if (plugin.rcFile) { - plugin.rcFile = deeplySubstitute(plugin.rcFile, []) as RCFile + plugin.rcFile = deeplySubstitute(plugin.rcFile, []).unwrap( + 'cannot reference plugin options when specifying options' + ) as RCFile } config.resolutionTrackers.substitutedPlugins.add(plugin.id) } diff --git a/core/cli/test/options.test.ts b/core/cli/test/options.test.ts index d8652a55d..6b98dd439 100644 --- a/core/cli/test/options.test.ts +++ b/core/cli/test/options.test.ts @@ -106,4 +106,32 @@ options: `"cannot reference plugin options when specifying options"` ) }) + + it('should print multiple invalid tags in error', async () => { + mockedFs.readFile.mockResolvedValueOnce( + yaml(` +options: + plugins: + test: + !toolkit/if-defined 'test.foo': + foo: !toolkit/option 'test.foo' + other-test: + - bar: !toolkit/option 'test.bar' +`) + ) + + expect.assertions(2) + try { + await loadConfig(logger, { validate: false }) + } catch (error) { + expect(error.details.split('\n\n')).toHaveLength(3) + expect(error.details).toMatchInlineSnapshot(` + "YAML tag referencing options used at path 'options.plugins.test' + + YAML tag referencing options used at path 'options.plugins.test.foo' + + YAML tag referencing options used at path 'options.plugins.other-test.0.bar'" + `) + } + }) }) From 4ad1221840e3c869c3628796d3ce0b72f17cc7b7 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Tue, 23 Apr 2024 17:34:20 +0100 Subject: [PATCH 208/321] fix(typescript): point config to correct module path for task --- plugins/typescript/.toolkitrc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/typescript/.toolkitrc.yml b/plugins/typescript/.toolkitrc.yml index 9523ef286..554680e73 100644 --- a/plugins/typescript/.toolkitrc.yml +++ b/plugins/typescript/.toolkitrc.yml @@ -1,5 +1,5 @@ tasks: - TypeScript: './lib/tasks' + TypeScript: './lib/tasks/typescript' commands: # TODO add options here once we support per-command-assignment options From 0fa0bd78bfcef752ca21335fd7535366e46e79ed Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Wed, 24 Apr 2024 17:03:13 +0100 Subject: [PATCH 209/321] fix: bump TypeScript to fix import transpilation There was a bug with the version of TypeScript we were using which meant the path you wanted to import was stored in a global variable that was subject to race conditions if you were importing modules asynchronously, as we do in the entry-point.ts code in core/cli. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4346725ad..95f811b4e 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "prettier": "^2.8.8", "release-please": "^15.0.0", "ts-jest": "^27.1.3", - "typescript": "~4.9.5" + "typescript": "~5.4.5" }, "workspaces": [ "core/*", From 458798f267f2b9f3a701ead659fbd9b4635fc9f9 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Wed, 24 Apr 2024 17:12:36 +0100 Subject: [PATCH 210/321] test: bump jest and ts-jest to versions compatible with TypeScript 5 Fixed various incompatibilities introduced by the major version bump: - remove collectCoverage options from project settings as they cause a warning to be printed and don't seem to have any effect in projects - move ts-jest settings into transform option instead of globals as is now required - a minor version bump transitively required in Babel caused a babel plugin test to fail. update to use a snapshot so it's easier to fix in the future - update snapshots that are using now formats - remove jest dependencies from prettier plugin so that it uses the monorepo's versions - remove @jest/global dependency from jest plugin to allow the hoisted version of the jest-environment-node test environment to match the version of jest we're using so that it uses the correct export conditionals when resolving modules (test environments are themselves resolved independently and so the version installed within jest's node_modules is ignored) - include a Jest config in the core/sandbox directory to avoid a Jest bug where it will include all projects twice if one project directory is missing a config file --- core/cli/jest.config.js | 15 +- core/sandbox/.gitignore | 1 + core/sandbox/jest.config.js | 4 + jest.config.base.js | 17 +- jest.config.js | 3 +- lib/doppler/jest.config.js | 3 +- lib/validated/jest.config.js | 2 +- lib/vault/jest.config.js | 3 +- lib/vault/test/index.test.ts | 5 +- package-lock.json | 4156 +++++++++++------ package.json | 4 +- plugins/babel/jest.config.js | 2 +- .../babel/test/files/fixtures/transpiled.js | 10 - plugins/babel/test/tasks/babel.test.ts | 20 +- plugins/circleci-deploy/jest.config.js | 2 +- plugins/circleci-npm/jest.config.js | 2 +- plugins/circleci/jest.config.js | 2 +- plugins/eslint/jest.config.js | 2 +- plugins/heroku/jest.config.js | 3 +- plugins/husky-npm/jest.config.js | 2 +- plugins/jest/jest.config.js | 2 +- plugins/jest/package.json | 1 - plugins/lint-staged-npm/jest.config.js | 2 +- plugins/mocha/jest.config.js | 2 +- plugins/n-test/jest.config.js | 15 +- plugins/npm/jest.config.js | 2 +- plugins/npm/test/npm-publish.test.ts | 4 +- plugins/pa11y/jest.config.js | 2 +- plugins/package-json-hook/jest.config.js | 2 +- plugins/package-json-hook/test/index.test.ts | 38 +- plugins/prettier/jest.config.js | 2 +- plugins/prettier/package.json | 3 - plugins/prettier/test/tasks/prettier.test.ts | 1 - plugins/typescript/jest.config.js | 2 +- plugins/upload-assets-to-s3/jest.config.js | 2 +- plugins/webpack/jest.config.js | 2 +- 36 files changed, 2898 insertions(+), 1442 deletions(-) create mode 100644 core/sandbox/jest.config.js delete mode 100644 plugins/babel/test/files/fixtures/transpiled.js diff --git a/core/cli/jest.config.js b/core/cli/jest.config.js index 270a20916..9fbb18e03 100644 --- a/core/cli/jest.config.js +++ b/core/cli/jest.config.js @@ -2,11 +2,14 @@ const base = require('../../jest.config.base') const path = require('path') module.exports = { - ...base, - globals: { - 'ts-jest': { - ...base.globals['ts-jest'], - tsconfig: path.resolve(__dirname, './tsconfig.test.json') - } + ...base.config, + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + ...base.tsJestConfig, + tsconfig: path.resolve(__dirname, './tsconfig.test.json') + } + ] } } diff --git a/core/sandbox/.gitignore b/core/sandbox/.gitignore index fa454c38e..5c8ff07f9 100644 --- a/core/sandbox/.gitignore +++ b/core/sandbox/.gitignore @@ -1,3 +1,4 @@ * !readme.md !.gitignore +!jest.config.js diff --git a/core/sandbox/jest.config.js b/core/sandbox/jest.config.js new file mode 100644 index 000000000..73c77e8f5 --- /dev/null +++ b/core/sandbox/jest.config.js @@ -0,0 +1,4 @@ +// Jest seems to have a bug where a directory in its list of projects without a +// Jest config will cause all tests to be run twice. Let's leave a config here +// to prevent that. +module.exports = {} diff --git a/jest.config.base.js b/jest.config.base.js index 7813c156a..a69bf0446 100644 --- a/jest.config.base.js +++ b/jest.config.base.js @@ -1,13 +1,16 @@ -module.exports = { - preset: 'ts-jest', +const tsJestConfig = { + tsconfig: 'tsconfig.settings.json', + isolatedModules: true +} +module.exports.tsJestConfig = tsJestConfig + +/** @type {import('jest').Config} */ +module.exports.config = { testEnvironment: 'node', testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/*.+(spec|test).[jt]s?(x)'], testPathIgnorePatterns: ['/node_modules/', '/.+/lib/', '/test/files'], clearMocks: true, - globals: { - 'ts-jest': { - tsconfig: 'tsconfig.settings.json', - isolatedModules: true - } + transform: { + '^.+\\.tsx?$': ['ts-jest', tsJestConfig] } } diff --git a/jest.config.js b/jest.config.js index dc31563b7..0ad64a419 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,7 @@ const base = require('./jest.config.base') +/** @type {import('jest').Config} */ module.exports = { - ...base, + ...base.config, projects: ['/core/*', '/plugins/*', '/lib/*'] } diff --git a/lib/doppler/jest.config.js b/lib/doppler/jest.config.js index 8ae711e3d..91d4858ef 100644 --- a/lib/doppler/jest.config.js +++ b/lib/doppler/jest.config.js @@ -1,7 +1,6 @@ const base = require('../../jest.config.base') module.exports = { - ...base, - collectCoverage: true, + ...base.config, moduleDirectories: ['node_modules'] } diff --git a/lib/validated/jest.config.js b/lib/validated/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/lib/validated/jest.config.js +++ b/lib/validated/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/lib/vault/jest.config.js b/lib/vault/jest.config.js index 8ae711e3d..91d4858ef 100644 --- a/lib/vault/jest.config.js +++ b/lib/vault/jest.config.js @@ -1,7 +1,6 @@ const base = require('../../jest.config.base') module.exports = { - ...base, - collectCoverage: true, + ...base.config, moduleDirectories: ['node_modules'] } diff --git a/lib/vault/test/index.test.ts b/lib/vault/test/index.test.ts index a98b39e10..b7395d338 100644 --- a/lib/vault/test/index.test.ts +++ b/lib/vault/test/index.test.ts @@ -1,11 +1,10 @@ import { describe, it, beforeAll, beforeEach, afterAll, jest, expect } from '@jest/globals' import { VaultEnvVars } from '../src/index' import fetch from '@financial-times/n-fetch' -import { mocked } from 'ts-jest/utils' import fs from 'fs' import winston, { Logger } from 'winston' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger let CIRCLECI: string if (process.env.CIRCLECI) { @@ -15,7 +14,7 @@ const VAULT_AUTH_GITHUB_TOKEN = process.env.VAULT_AUTH_GITHUB_TOKEN || undefined jest.mock('@financial-times/n-fetch') -const mockedFetch = mocked(fetch, true) +const mockedFetch = jest.mocked(fetch, true) jest.mock('path', () => { return { diff --git a/package-lock.json b/package-lock.json index 11cc36550..abd4a9f38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,12 +33,12 @@ "eslint-config-prettier": "^8.8.0", "eslint-plugin-import": "^2.27.5", "husky": "^4.3.8", - "jest": "^27.4.7", + "jest": "^29.7.0", "lint-staged": "^10.5.4", "prettier": "^2.8.8", "release-please": "^15.0.0", - "ts-jest": "^27.1.3", - "typescript": "~4.9.5" + "ts-jest": "^29.1.2", + "typescript": "~5.4.5" }, "engines": { "node": "18.x || 20.x", @@ -4452,38 +4452,45 @@ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@babel/code-frame": { - "version": "7.12.11", - "license": "MIT", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dependencies": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.17.10", - "license": "MIT", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.17.10", - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.9", - "@babel/parser": "^7.17.10", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.10", - "@babel/types": "^7.17.10", - "convert-source-map": "^1.7.0", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", + "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.4", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -4493,35 +4500,41 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/@babel/code-frame": { - "version": "7.16.7", - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "license": "ISC", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.17.10", - "license": "MIT", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dependencies": { - "@babel/types": "^7.17.10", - "@jridgewell/gen-mapping": "^0.1.0", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.16.7", "dev": true, @@ -4546,28 +4559,41 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.17.10", - "license": "MIT", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.20.2", - "semver": "^6.3.0" + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "license": "ISC", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.17.9", "dev": true, @@ -4630,11 +4656,9 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.16.7" - }, + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } @@ -4651,21 +4675,23 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "license": "MIT", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "license": "MIT", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -4683,30 +4709,32 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "license": "MIT", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.17.7", - "license": "MIT", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-optimise-call-expression": { @@ -4757,10 +4785,11 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.17.7", - "license": "MIT", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dependencies": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -4778,26 +4807,36 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "license": "MIT", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "license": "MIT", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "engines": { "node": ">=6.9.0" } @@ -4817,25 +4856,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.17.9", - "license": "MIT", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", + "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -4899,8 +4940,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.17.10", - "license": "MIT", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -5261,7 +5303,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -5976,56 +6017,38 @@ } }, "node_modules/@babel/template": { - "version": "7.16.7", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template/node_modules/@babel/code-frame": { - "version": "7.16.7", - "license": "MIT", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.17.10", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.10", - "@babel/types": "^7.17.10", - "debug": "^4.1.0", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dependencies": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.16.7", - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", "license": "MIT", @@ -6034,10 +6057,12 @@ } }, "node_modules/@babel/types": { - "version": "7.17.10", - "license": "MIT", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -6046,7 +6071,8 @@ }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, "node_modules/@colors/colors": { "version": "1.5.0", @@ -6179,6 +6205,19 @@ "node": ">=v12" } }, + "node_modules/@commitlint/load/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@commitlint/message": { "version": "16.2.1", "dev": true, @@ -6286,7 +6325,7 @@ }, "node_modules/@cspotcode/source-map-consumer": { "version": "0.8.0", - "devOptional": true, + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">= 12" @@ -6294,7 +6333,7 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.7.0", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-consumer": "0.8.0" @@ -7193,55 +7232,135 @@ } }, "node_modules/@jest/console": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/core": { - "version": "27.5.1", - "license": "MIT", + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dependencies": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.8.1", + "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "rimraf": "^3.0.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -7252,34 +7371,59 @@ } } }, - "node_modules/@jest/core/node_modules/acorn": { - "version": "8.7.1", - "license": "MIT", + "node_modules/@jest/core/node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "optional": true, "peer": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/@jest/core/node_modules/acorn-walk": { - "version": "8.2.0", - "license": "MIT", + "node_modules/@jest/core/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "optional": true, "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "engines": { - "node": ">=0.4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/@jest/core/node_modules/ci-info": { - "version": "3.3.0", - "license": "MIT" - }, - "node_modules/@jest/core/node_modules/diff": { - "version": "4.0.2", - "license": "BSD-3-Clause", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "optional": true, "peer": true, "engines": { @@ -7287,53 +7431,118 @@ } }, "node_modules/@jest/core/node_modules/jest-config": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", - "glob": "^7.1.1", + "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { + "@types/node": "*", "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, "ts-node": { "optional": true } } }, + "node_modules/@jest/core/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/@jest/core/node_modules/ts-node": { - "version": "10.7.0", - "license": "MIT", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "optional": true, "peer": true, "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -7344,7 +7553,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -7372,6 +7581,7 @@ }, "node_modules/@jest/environment": { "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { "@jest/fake-timers": "^27.5.1", @@ -7383,109 +7593,57 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@jest/expect": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", - "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", + "node_modules/@jest/environment/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", "dev": true, "dependencies": { - "expect": "^29.3.1", - "jest-snapshot": "^29.3.1" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@jest/expect-utils": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", - "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", - "dev": true, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dependencies": { - "jest-get-type": "^29.2.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect-utils/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect/node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@jest/expect/node_modules/@jest/transform": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", - "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", - "dev": true, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.3.1", - "@jridgewell/trace-mapping": "^0.3.15", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.3.1", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.1" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect/node_modules/@jest/types": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", - "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.0.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, + "node_modules/@jest/expect-utils/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect/node_modules/@types/yargs": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.17.tgz", - "integrity": "sha512-72bWxFKTK6uwWJAVT+3rF6Jo6RTojiJ27FQo8Rf60AL+VZbzoVPnMFhKsUnbjR8A3BTCYQ7Mv3hnl8T0A+CX9g==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/@jest/expect/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, "engines": { "node": ">=10" }, @@ -7494,122 +7652,90 @@ } }, "node_modules/@jest/expect/node_modules/ci-info": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", - "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", - "dev": true, + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "engines": { "node": ">=8" } }, - "node_modules/@jest/expect/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "node_modules/@jest/expect/node_modules/diff-sequences": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", - "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect/node_modules/expect": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", - "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dependencies": { - "@jest/expect-utils": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect/node_modules/jest-diff": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", - "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect/node_modules/jest-get-type": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", - "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect/node_modules/jest-haste-map": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", - "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", - "dev": true, - "dependencies": { - "@jest/types": "^29.3.1", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", - "jest-worker": "^29.3.1", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, "node_modules/@jest/expect/node_modules/jest-matcher-utils": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", - "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "pretty-format": "^29.3.1" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect/node_modules/jest-message-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", - "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.3.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -7617,57 +7743,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect/node_modules/jest-regex-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", - "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect/node_modules/jest-snapshot": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", - "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.3.1", - "@jest/transform": "^29.3.1", - "@jest/types": "^29.3.1", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.3.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.3.1", - "jest-get-type": "^29.2.0", - "jest-haste-map": "^29.3.1", - "jest-matcher-utils": "^29.3.1", - "jest-message-util": "^29.3.1", - "jest-util": "^29.3.1", - "natural-compare": "^1.4.0", - "pretty-format": "^29.3.1", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jest/expect/node_modules/jest-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", - "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -7678,28 +7759,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/expect/node_modules/jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.3.1", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jest/expect/node_modules/pretty-format": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -7710,96 +7775,101 @@ "node_modules/@jest/expect/node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, - "node_modules/@jest/expect/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/@jest/fake-timers": { + "version": "27.5.1", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@jest/expect/node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "node_modules/@jest/fake-timers/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", "dev": true, "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@jest/fake-timers": { + "node_modules/@jest/globals": { "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { + "@jest/environment": "^27.5.1", "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "expect": "^27.5.1" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@jest/globals": { + "node_modules/@jest/globals/node_modules/@jest/types": { "version": "27.5.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" }, "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/@jest/reporters": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", - "glob": "^7.1.2", + "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", - "source-map": "^0.6.0", "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -7810,92 +7880,270 @@ } } }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/@jest/schemas": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", - "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dependencies": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "27.5.1", - "license": "MIT", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" + "graceful-fs": "^4.2.9" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dependencies": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dependencies": { - "@jest/test-result": "^27.5.1", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" + "write-file-atomic": "^4.0.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/@jest/types": { - "version": "27.5.1", - "license": "MIT", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dependencies": { + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "@types/yargs": "^16.0.0", + "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dependencies": { + "@types/yargs-parser": "*" } }, "node_modules/@jridgewell/gen-mapping": { @@ -7918,8 +8166,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.0", - "license": "MIT", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -7930,12 +8179,12 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@kwsites/file-exists": { @@ -9510,10 +9759,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", - "dev": true + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "node_modules/@sindresorhus/is": { "version": "0.14.0", @@ -9525,6 +9773,7 @@ }, "node_modules/@sinonjs/commons": { "version": "1.8.3", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "type-detect": "4.0.8" @@ -9532,6 +9781,7 @@ }, "node_modules/@sinonjs/fake-timers": { "version": "8.1.0", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.7.0" @@ -9583,26 +9833,29 @@ "devOptional": true }, "node_modules/@types/babel__core": { - "version": "7.1.19", - "license": "MIT", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "node_modules/@types/babel__generator": { - "version": "7.6.4", - "license": "MIT", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.1", - "license": "MIT", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -9832,10 +10085,6 @@ "version": "4.0.0", "license": "MIT" }, - "node_modules/@types/prettier": { - "version": "2.6.0", - "license": "MIT" - }, "node_modules/@types/prompts": { "version": "2.0.14", "dev": true, @@ -10421,10 +10670,6 @@ "es5-ext": "^0.10.47" } }, - "node_modules/abab": { - "version": "2.0.6", - "license": "BSD-3-Clause" - }, "node_modules/abbrev": { "version": "1.1.1", "license": "ISC" @@ -10441,8 +10686,10 @@ } }, "node_modules/acorn": { - "version": "7.4.1", - "license": "MIT", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -10450,14 +10697,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "license": "MIT", - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "dev": true, @@ -10467,8 +10706,10 @@ } }, "node_modules/acorn-walk": { - "version": "7.2.0", - "license": "MIT", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "devOptional": true, "engines": { "node": ">=0.4.0" } @@ -11156,20 +11397,20 @@ } }, "node_modules/babel-jest": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" @@ -11198,16 +11439,17 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "license": "MIT", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", + "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/babel-plugin-polyfill-corejs2": { @@ -11276,14 +11518,15 @@ } }, "node_modules/babel-preset-jest": { - "version": "27.5.1", - "license": "MIT", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -11520,10 +11763,6 @@ "version": "1.1.0", "license": "MIT" }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "license": "BSD-2-Clause" - }, "node_modules/browser-stdout": { "version": "1.3.1", "license": "ISC", @@ -11609,7 +11848,9 @@ } }, "node_modules/browserslist": { - "version": "4.20.3", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "funding": [ { "type": "opencollective", @@ -11618,15 +11859,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001332", - "electron-to-chromium": "^1.4.118", - "escalade": "^3.1.1", - "node-releases": "^2.0.3", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -11911,7 +12154,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001336", + "version": "1.0.30001612", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001612.tgz", + "integrity": "sha512-lFgnZ07UhaCcsSZgWW0K5j4e69dK1u/ltrL9lTUiFOwNHs12S3UMIEYgBV0Z6C6hRDev7iRnMzzYmKabYdXF9g==", "funding": [ { "type": "opencollective", @@ -11920,9 +12165,12 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ], - "license": "CC-BY-4.0" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, "node_modules/caseless": { "version": "0.12.0", @@ -12796,11 +13044,9 @@ } }, "node_modules/convert-source-map": { - "version": "1.8.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookiejar": { "version": "2.1.4", @@ -12908,25 +13154,6 @@ "typescript": ">=3" } }, - "node_modules/cosmiconfig-typescript-loader/node_modules/acorn": { - "version": "8.7.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/cosmiconfig-typescript-loader/node_modules/acorn-walk": { - "version": "8.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/cosmiconfig-typescript-loader/node_modules/diff": { "version": "4.0.2", "dev": true, @@ -13064,6 +13291,215 @@ "sha.js": "^2.4.8" } }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "optional": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/create-jest/node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "optional": true, + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/create-jest/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/create-jest/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/create-jest/node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "optional": true, + "peer": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, "node_modules/create-require": { "version": "1.1.1", "devOptional": true, @@ -13193,24 +13629,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cssom": { - "version": "0.4.4", - "license": "MIT" - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "license": "MIT", - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "license": "MIT" - }, "node_modules/cwise-compiler": { "version": "1.1.3", "license": "MIT", @@ -13272,18 +13690,6 @@ "version": "0.0.3", "license": "MIT" }, - "node_modules/data-urls": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", @@ -13389,10 +13795,6 @@ "node": ">=0.10.0" } }, - "node_modules/decimal.js": { - "version": "10.3.1", - "license": "MIT" - }, "node_modules/decode-uri-component": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", @@ -13822,7 +14224,8 @@ }, "node_modules/detect-newline": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "engines": { "node": ">=8" } @@ -13851,6 +14254,7 @@ }, "node_modules/diff-sequences": { "version": "27.5.1", + "dev": true, "license": "MIT", "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" @@ -13925,23 +14329,6 @@ ], "license": "BSD-2-Clause" }, - "node_modules/domexception": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=8" - } - }, "node_modules/domhandler": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", @@ -14070,8 +14457,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.134", - "license": "ISC" + "version": "1.4.747", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.747.tgz", + "integrity": "sha512-+FnSWZIAvFHbsNVmUxhEqWiaOiPMcfum1GQzlWCg/wLigVtshOsjXHyEFfmt6cFK6+HkS3QOJBv6/3OPumbBfw==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -14091,10 +14479,11 @@ "license": "MIT" }, "node_modules/emittery": { - "version": "0.8.1", - "license": "MIT", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sindresorhus/emittery?sponsor=1" @@ -14471,98 +14860,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "2.0.0", - "license": "BSD-2-Clause", + "node_modules/eslint": { + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", + "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", + "dev": true, "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "5.3.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.37.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.37.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", - "esquery": "^1.4.2", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.2", + "@eslint/js": "8.37.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.4.0", + "espree": "^9.5.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", @@ -14878,18 +15198,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/espree/node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", @@ -14968,6 +15276,7 @@ }, "node_modules/esutils": { "version": "2.0.3", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -15108,6 +15417,7 @@ }, "node_modules/expect": { "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^27.5.1", @@ -15119,6 +15429,22 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/expect/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, "node_modules/ext": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", @@ -15329,6 +15655,7 @@ }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "dev": true, "license": "MIT" }, "node_modules/fast-redact": { @@ -16704,19 +17031,10 @@ "node": ">=6" } }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/html-escaper": { "version": "2.0.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" }, "node_modules/htmlparser2": { "version": "8.0.1", @@ -17573,10 +17891,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "license": "MIT" - }, "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -17826,20 +18140,66 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "license": "BSD-3-Clause", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -17850,8 +18210,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.4", - "license": "BSD-3-Clause", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -17870,19 +18231,21 @@ } }, "node_modules/jest": { - "version": "27.5.1", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, - "license": "MIT", "dependencies": { - "@jest/core": "^27.5.1", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^27.5.1" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -17894,159 +18257,457 @@ } }, "node_modules/jest-changed-files": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dependencies": { - "@jest/types": "^27.5.1", "execa": "^5.0.0", - "throat": "^6.0.1" + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-changed-files/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-cli": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-circus/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dependencies": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - }, - "bin": { - "jest": "bin/jest.js" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-cli/node_modules/acorn": { - "version": "8.7.1", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" + "node_modules/jest-circus/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-cli/node_modules/acorn-walk": { - "version": "8.2.0", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.4.0" + "node_modules/jest-circus/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": { + "type-detect": "4.0.8" } }, - "node_modules/jest-cli/node_modules/ci-info": { - "version": "3.3.0", - "license": "MIT" + "node_modules/jest-circus/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } }, - "node_modules/jest-cli/node_modules/diff": { - "version": "4.0.2", - "license": "BSD-3-Clause", - "optional": true, - "peer": true, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "engines": { - "node": ">=0.3.1" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-cli/node_modules/jest-config": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-circus/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/jest-circus/node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "optional": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "optional": true, + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/jest-cli/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", - "glob": "^7.1.1", + "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { + "@types/node": "*", "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, "ts-node": { "optional": true } } }, + "node_modules/jest-cli/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/jest-cli/node_modules/ts-node": { - "version": "10.7.0", - "license": "MIT", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "optional": true, "peer": true, "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -18057,7 +18718,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -18083,24 +18744,9 @@ } } }, - "node_modules/jest-cli/node_modules/yargs": { - "version": "16.2.0", - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jest-diff": { "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.0.0", @@ -18113,130 +18759,365 @@ } }, "node_modules/jest-docblock": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dependencies": { "detect-newline": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-environment-jsdom": { - "version": "27.5.1", - "license": "MIT", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=8" } }, - "node_modules/jest-environment-node": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-each/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/jest-environment-node/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-environment-node/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-environment-node/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/jest-get-type": { "version": "27.5.1", + "dev": true, "license": "MIT", "engines": { "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, "node_modules/jest-haste-map": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dependencies": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, - "node_modules/jest-jasmine2": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-haste-map/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-haste-map/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-leak-detector": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dependencies": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-leak-detector/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-leak-detector/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-leak-detector/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/jest-matcher-utils": { "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.0.0", @@ -18250,6 +19131,7 @@ }, "node_modules/jest-message-util": { "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", @@ -18266,185 +19148,694 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/jest-message-util/node_modules/@babel/code-frame": { - "version": "7.16.7", + "node_modules/jest-message-util/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.16.7" + "@jest/types": "^27.5.1", + "@types/node": "*" }, "engines": { - "node": ">=6.9.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/jest-runner/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/jest-runtime/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-mock": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-snapshot/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" + "node_modules/jest-snapshot/node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-regex-util": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-snapshot/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dependencies": { - "@jest/types": "^27.5.1", "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-resolve-dependencies": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-snapshot/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dependencies": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runner": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-snapshot/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.8.1", + "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" + "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-snapshot/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" } }, - "node_modules/jest-serializer": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-snapshot/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.9" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot": { - "version": "27.5.1", - "license": "MIT", + "node_modules/jest-snapshot/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" } }, + "node_modules/jest-snapshot/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/jest-util": { "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { "@jest/types": "^27.5.1", @@ -18458,28 +19849,58 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/jest-util/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, "node_modules/jest-util/node_modules/ci-info": { "version": "3.3.0", + "dev": true, "license": "MIT" }, "node_modules/jest-validate": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^27.5.1" + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/jest-validate/node_modules/camelcase": { "version": "6.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "engines": { "node": ">=10" }, @@ -18487,37 +19908,128 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/jest-validate/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/jest-watcher": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^27.5.1", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker": { - "version": "27.5.1", - "license": "MIT", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dependencies": { "@types/node": "*", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker/node_modules/supports-color": { "version": "8.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dependencies": { "has-flag": "^4.0.0" }, @@ -18597,60 +20109,6 @@ "version": "0.1.1", "license": "MIT" }, - "node_modules/jsdom": { - "version": "16.7.0", - "license": "MIT", - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/acorn": { - "version": "8.7.1", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/jsesc": { "version": "2.5.2", "license": "MIT", @@ -19629,6 +21087,7 @@ "node_modules/make-dir": { "version": "3.1.0", "license": "MIT", + "peer": true, "dependencies": { "semver": "^6.0.0" }, @@ -19642,6 +21101,7 @@ "node_modules/make-dir/node_modules/semver": { "version": "6.3.0", "license": "ISC", + "peer": true, "bin": { "semver": "bin/semver.js" } @@ -20856,8 +22316,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.4", - "license": "MIT" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/node-schedule": { "version": "2.1.1", @@ -21496,10 +22957,6 @@ "node": ">=0.10.0" } }, - "node_modules/nwsapi": { - "version": "2.2.0", - "license": "MIT" - }, "node_modules/oauth-sign": { "version": "0.9.0", "license": "Apache-2.0", @@ -22652,10 +24109,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5": { - "version": "6.0.1", - "license": "MIT" - }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", @@ -23148,6 +24601,7 @@ }, "node_modules/pretty-format": { "version": "27.5.1", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1", @@ -23160,6 +24614,7 @@ }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -23397,6 +24852,21 @@ } } }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/q": { "version": "1.5.1", "dev": true, @@ -23495,6 +24965,7 @@ }, "node_modules/react-is": { "version": "17.0.2", + "dev": true, "license": "MIT" }, "node_modules/read-package-json": { @@ -24091,6 +25562,19 @@ "node": ">= 6" } }, + "node_modules/release-please/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "license": "ISC", @@ -24247,8 +25731,9 @@ "license": "MIT" }, "node_modules/resolve.exports": { - "version": "1.1.0", - "license": "MIT", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "engines": { "node": ">=10" } @@ -24473,16 +25958,6 @@ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", "peer": true }, - "node_modules/saxes": { - "version": "5.0.1", - "license": "ISC", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/scarlet": { "version": "2.0.20", "license": "MIT", @@ -26569,17 +28044,6 @@ "node": ">=8" } }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "license": "MIT", @@ -26590,10 +28054,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "license": "MIT" - }, "node_modules/tapable": { "version": "1.1.3", "license": "MIT", @@ -26773,20 +28233,6 @@ "rimraf": "bin.js" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/terser": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", @@ -26951,10 +28397,6 @@ "real-require": "^0.2.0" } }, - "node_modules/throat": { - "version": "6.0.1", - "license": "MIT" - }, "node_modules/through": { "version": "2.3.8", "license": "MIT" @@ -27189,35 +28631,6 @@ "nopt": "bin/nopt.js" } }, - "node_modules/tough-cookie": { - "version": "4.0.0", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.1.2", - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/traverse": { "version": "0.6.7", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", @@ -27266,37 +28679,38 @@ "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" }, "node_modules/ts-jest": { - "version": "27.1.4", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", "dev": true, - "license": "MIT", "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "@types/jest": "^27.0.0", - "babel-jest": ">=27.0.0 <28", - "jest": "^27.0.0", - "typescript": ">=3.8 <5.0" + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { "@babel/core": { "optional": true }, - "@types/jest": { + "@jest/types": { "optional": true }, "babel-jest": { @@ -27307,6 +28721,80 @@ } } }, + "node_modules/ts-jest/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-jest/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/ts-node": { "version": "8.10.2", "dev": true, @@ -27518,21 +29006,22 @@ "node_modules/typedarray-to-buffer": { "version": "3.1.5", "license": "MIT", + "peer": true, "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uglify-js": { @@ -27801,6 +29290,35 @@ "yarn": "*" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/update-notifier": { "version": "5.1.0", "license": "BSD-2-Clause", @@ -27909,24 +29427,18 @@ "license": "MIT" }, "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "license": "ISC", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.3", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "license": "Apache-2.0", @@ -27980,23 +29492,6 @@ "version": "1.1.2", "license": "MIT" }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/wait-port": { "version": "0.2.9", "license": "MIT", @@ -28461,13 +29956,6 @@ "node": ">= 8.11.0" } }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=10.4" - } - }, "node_modules/webpack": { "version": "4.46.0", "license": "MIT", @@ -28772,43 +30260,10 @@ "node": ">=0.10.0" } }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "license": "MIT", - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.4.24", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/whatwg-fetch": { "version": "3.6.2", "license": "MIT" }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "license": "MIT" - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "license": "MIT", - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/which": { "version": "1.3.1", "license": "ISC", @@ -28914,6 +30369,7 @@ }, "node_modules/word-wrap": { "version": "1.2.3", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -28957,6 +30413,7 @@ "node_modules/write-file-atomic": { "version": "3.0.3", "license": "ISC", + "peer": true, "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", @@ -29058,10 +30515,6 @@ "node": ">=8" } }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "license": "Apache-2.0" - }, "node_modules/xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -29081,10 +30534,6 @@ "node": ">=4.0" } }, - "node_modules/xmlchars": { - "version": "2.2.0", - "license": "MIT" - }, "node_modules/xpath": { "version": "0.0.32", "dev": true, @@ -29151,7 +30600,6 @@ }, "node_modules/yargs": { "version": "17.4.1", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^7.0.2", @@ -29219,7 +30667,6 @@ }, "node_modules/yargs/node_modules/yargs-parser": { "version": "21.0.1", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -29908,7 +31355,6 @@ }, "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0", - "@jest/globals": "^27.4.6", "winston": "^3.5.1" }, "engines": { @@ -30658,10 +32104,7 @@ "tslib": "^2.3.1" }, "devDependencies": { - "@jest/globals": "^27.4.6", "@types/prettier": "^2.7.3", - "jest": "^27.4.7", - "ts-jest": "^27.1.3", "winston": "^3.5.1" }, "engines": { @@ -30942,6 +32385,19 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "plugins/typescript/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "plugins/upload-assets-to-s3": { "name": "@dotcom-tool-kit/upload-assets-to-s3", "version": "3.2.0", diff --git a/package.json b/package.json index 95f811b4e..2ad23ef14 100644 --- a/package.json +++ b/package.json @@ -34,11 +34,11 @@ "eslint-config-prettier": "^8.8.0", "eslint-plugin-import": "^2.27.5", "husky": "^4.3.8", - "jest": "^27.4.7", + "jest": "^29.7.0", "lint-staged": "^10.5.4", "prettier": "^2.8.8", "release-please": "^15.0.0", - "ts-jest": "^27.1.3", + "ts-jest": "^29.1.2", "typescript": "~5.4.5" }, "workspaces": [ diff --git a/plugins/babel/jest.config.js b/plugins/babel/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/babel/jest.config.js +++ b/plugins/babel/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/babel/test/files/fixtures/transpiled.js b/plugins/babel/test/files/fixtures/transpiled.js deleted file mode 100644 index ed1234556..000000000 --- a/plugins/babel/test/files/fixtures/transpiled.js +++ /dev/null @@ -1,10 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.test = test; - -function test(x) { - return x !== null && x !== void 0 ? x : 0; -} \ No newline at end of file diff --git a/plugins/babel/test/tasks/babel.test.ts b/plugins/babel/test/tasks/babel.test.ts index 13f0851ce..c3dfcdc35 100644 --- a/plugins/babel/test/tasks/babel.test.ts +++ b/plugins/babel/test/tasks/babel.test.ts @@ -1,4 +1,4 @@ -import { beforeAll, describe, expect, it } from '@jest/globals' +import { describe, expect, it } from '@jest/globals' import Babel from '../../src/tasks/babel' import { promises as fs } from 'fs' import * as path from 'path' @@ -10,12 +10,6 @@ const testDirectory = path.join(__dirname, '../files') const outputPath = path.join(testDirectory, 'lib') describe('babel', () => { - let transpiledFixture: string - - beforeAll(async () => { - transpiledFixture = await fs.readFile(path.join(testDirectory, 'fixtures/transpiled.js'), 'utf8') - }) - it('should transpile the file', async () => { const task = new Babel( logger, @@ -30,6 +24,16 @@ describe('babel', () => { ) await task.run() const transpiled = await fs.readFile(path.join(outputPath, 'index.js'), 'utf8') - expect(transpiled).toEqual(transpiledFixture) + expect(transpiled).toMatchInlineSnapshot(` + ""use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.test = test; + function test(x) { + return x !== null && x !== void 0 ? x : 0; + }" + `) }) }) diff --git a/plugins/circleci-deploy/jest.config.js b/plugins/circleci-deploy/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/circleci-deploy/jest.config.js +++ b/plugins/circleci-deploy/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/circleci-npm/jest.config.js b/plugins/circleci-npm/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/circleci-npm/jest.config.js +++ b/plugins/circleci-npm/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/circleci/jest.config.js b/plugins/circleci/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/circleci/jest.config.js +++ b/plugins/circleci/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/eslint/jest.config.js b/plugins/eslint/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/eslint/jest.config.js +++ b/plugins/eslint/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/heroku/jest.config.js b/plugins/heroku/jest.config.js index e427ce8cb..2ea38bb31 100644 --- a/plugins/heroku/jest.config.js +++ b/plugins/heroku/jest.config.js @@ -1,6 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base, - collectCoverage: true + ...base.config } diff --git a/plugins/husky-npm/jest.config.js b/plugins/husky-npm/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/husky-npm/jest.config.js +++ b/plugins/husky-npm/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/jest/jest.config.js b/plugins/jest/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/jest/jest.config.js +++ b/plugins/jest/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/jest/package.json b/plugins/jest/package.json index fb50d453d..4d712c11e 100644 --- a/plugins/jest/package.json +++ b/plugins/jest/package.json @@ -31,7 +31,6 @@ ], "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0", - "@jest/globals": "^27.4.6", "winston": "^3.5.1" }, "engines": { diff --git a/plugins/lint-staged-npm/jest.config.js b/plugins/lint-staged-npm/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/lint-staged-npm/jest.config.js +++ b/plugins/lint-staged-npm/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/mocha/jest.config.js b/plugins/mocha/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/mocha/jest.config.js +++ b/plugins/mocha/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/n-test/jest.config.js b/plugins/n-test/jest.config.js index 270a20916..9fbb18e03 100644 --- a/plugins/n-test/jest.config.js +++ b/plugins/n-test/jest.config.js @@ -2,11 +2,14 @@ const base = require('../../jest.config.base') const path = require('path') module.exports = { - ...base, - globals: { - 'ts-jest': { - ...base.globals['ts-jest'], - tsconfig: path.resolve(__dirname, './tsconfig.test.json') - } + ...base.config, + transform: { + '^.+\\.tsx?$': [ + 'ts-jest', + { + ...base.tsJestConfig, + tsconfig: path.resolve(__dirname, './tsconfig.test.json') + } + ] } } diff --git a/plugins/npm/jest.config.js b/plugins/npm/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/npm/jest.config.js +++ b/plugins/npm/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/npm/test/npm-publish.test.ts b/plugins/npm/test/npm-publish.test.ts index 6e0005887..ac65fc8ef 100644 --- a/plugins/npm/test/npm-publish.test.ts +++ b/plugins/npm/test/npm-publish.test.ts @@ -6,7 +6,7 @@ import { publish } from 'libnpmpublish' import pack from 'libnpmpack' import { writeFile } from 'fs/promises' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger const readStateMock = jest.spyOn(state, 'readState') jest.spyOn(pacote, 'manifest').mockImplementation(() => Promise.resolve({} as ManifestResult)) @@ -69,7 +69,7 @@ describe('NpmPublish', () => { await expect(async () => { await task.run() }).rejects.toThrowErrorMatchingInlineSnapshot( - `"The Tool Kit \`ci\` state \`tag\` variable random-branch does not match regex /^v\\\\d+\\\\.\\\\d+\\\\.\\\\d+(-.+)?/. Configure your release version to match the regex eg. v1.2.3-beta.8"` + `"The Tool Kit \`ci\` state \`tag\` variable random-branch does not match regex /^v\\d+\\.\\d+\\.\\d+(-.+)?/. Configure your release version to match the regex eg. v1.2.3-beta.8"` ) }) diff --git a/plugins/pa11y/jest.config.js b/plugins/pa11y/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/pa11y/jest.config.js +++ b/plugins/pa11y/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/package-json-hook/jest.config.js b/plugins/package-json-hook/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/package-json-hook/jest.config.js +++ b/plugins/package-json-hook/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/package-json-hook/test/index.test.ts b/plugins/package-json-hook/test/index.test.ts index 322d198e0..82d0644c6 100644 --- a/plugins/package-json-hook/test/index.test.ts +++ b/plugins/package-json-hook/test/index.test.ts @@ -6,7 +6,7 @@ import winston, { Logger } from 'winston' import { HookInstallation } from '@dotcom-tool-kit/base' import { PackageJsonSchema } from '@dotcom-tool-kit/schemas/lib/hooks/package-json' -const logger = (winston as unknown) as Logger +const logger = winston as unknown as Logger describe('package.json hook', () => { const originalDir = process.cwd() @@ -71,8 +71,8 @@ describe('package.json hook', () => { const packageJson = JSON.parse(await fs.readFile(pkgPath, 'utf-8')) expect(packageJson).toMatchInlineSnapshot(` - Object { - "scripts": Object { + { + "scripts": { "test-hook": "dotcom-tool-kit test:hook", }, } @@ -105,8 +105,8 @@ describe('package.json hook', () => { const packageJson = JSON.parse(await fs.readFile(pkgPath, 'utf-8')) expect(packageJson).toMatchInlineSnapshot(` - Object { - "scripts": Object { + { + "scripts": { "test-hook": "dotcom-tool-kit test:hook --", }, } @@ -136,9 +136,9 @@ describe('package.json hook', () => { const packageJson = JSON.parse(await fs.readFile(pkgPath, 'utf-8')) expect(packageJson).toMatchInlineSnapshot(` - Object { - "scripts": Object { - "nested": Object { + { + "scripts": { + "nested": { "test-hook": "dotcom-tool-kit test:hook", }, }, @@ -189,7 +189,7 @@ describe('package.json hook', () => { expect( PackageJson.mergeChildInstallations( plugin, - (childInstallations as unknown) as HookInstallation>[] + childInstallations as unknown as HookInstallation>[] ) ).toEqual([ { @@ -238,7 +238,7 @@ describe('package.json hook', () => { expect( PackageJson.mergeChildInstallations( plugin, - (childInstallations as unknown) as HookInstallation>[] + childInstallations as unknown as HookInstallation>[] ) ).toEqual([ { @@ -297,7 +297,7 @@ describe('package.json hook', () => { expect( PackageJson.mergeChildInstallations( plugin, - (childInstallations as unknown) as HookInstallation>[] + childInstallations as unknown as HookInstallation>[] ) ).toEqual([ { @@ -372,8 +372,8 @@ describe('package.json hook', () => { expect( PackageJson.overrideChildInstallations( plugin, - (parentInstallation as unknown) as HookInstallation>, - (childInstallations as unknown) as HookInstallation>[] + parentInstallation as unknown as HookInstallation>, + childInstallations as unknown as HookInstallation>[] ) ).toEqual([ { @@ -437,8 +437,8 @@ describe('package.json hook', () => { expect( PackageJson.overrideChildInstallations( plugin, - (parentInstallation as unknown) as HookInstallation>, - (childInstallations as unknown) as HookInstallation>[] + parentInstallation as unknown as HookInstallation>, + childInstallations as unknown as HookInstallation>[] ) ).toEqual([ { @@ -499,8 +499,8 @@ describe('package.json hook', () => { expect( PackageJson.overrideChildInstallations( plugin, - (parentInstallation as unknown) as HookInstallation>, - (childInstallations as unknown) as HookInstallation>[] + parentInstallation as unknown as HookInstallation>, + childInstallations as unknown as HookInstallation>[] ) ).toEqual([ { @@ -595,8 +595,8 @@ describe('package.json hook', () => { expect( PackageJson.overrideChildInstallations( plugin, - (parentInstallation as unknown) as HookInstallation>, - (childInstallations as unknown) as HookInstallation>[] + parentInstallation as unknown as HookInstallation>, + childInstallations as unknown as HookInstallation>[] ) ).toEqual([ { diff --git a/plugins/prettier/jest.config.js b/plugins/prettier/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/prettier/jest.config.js +++ b/plugins/prettier/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/prettier/package.json b/plugins/prettier/package.json index d5e92bf73..c7899de87 100644 --- a/plugins/prettier/package.json +++ b/plugins/prettier/package.json @@ -31,10 +31,7 @@ ".toolkitrc.yml" ], "devDependencies": { - "@jest/globals": "^27.4.6", "@types/prettier": "^2.7.3", - "jest": "^27.4.7", - "ts-jest": "^27.1.3", "winston": "^3.5.1" }, "volta": { diff --git a/plugins/prettier/test/tasks/prettier.test.ts b/plugins/prettier/test/tasks/prettier.test.ts index 28da6ca8f..ba18f6806 100644 --- a/plugins/prettier/test/tasks/prettier.test.ts +++ b/plugins/prettier/test/tasks/prettier.test.ts @@ -1,4 +1,3 @@ -import { describe, it, expect, beforeAll } from '@jest/globals' import * as path from 'path' import Prettier from '../../src/tasks/prettier' import { promises as fsp } from 'fs' diff --git a/plugins/typescript/jest.config.js b/plugins/typescript/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/typescript/jest.config.js +++ b/plugins/typescript/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/upload-assets-to-s3/jest.config.js b/plugins/upload-assets-to-s3/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/upload-assets-to-s3/jest.config.js +++ b/plugins/upload-assets-to-s3/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } diff --git a/plugins/webpack/jest.config.js b/plugins/webpack/jest.config.js index 24889bbe6..2ea38bb31 100644 --- a/plugins/webpack/jest.config.js +++ b/plugins/webpack/jest.config.js @@ -1,5 +1,5 @@ const base = require('../../jest.config.base') module.exports = { - ...base + ...base.config } From e72263194fddc5f46dd0e71c66cbaaf35495d9f1 Mon Sep 17 00:00:00 2001 From: Ivo Murrell Date: Thu, 25 Apr 2024 16:08:13 +0100 Subject: [PATCH 211/321] fix(cli): only override child options for hooks of the same class This avoids an issue we were having where PackageJson options were being passed to CircleCi, which would insert its default fields in, causing the PackageJson schema to later fail. --- core/cli/src/plugin/reduce-installations.ts | 22 +++++++++++-------- .../multiple-hook-options/.toolkitrc.yml | 12 ++++++++++ core/cli/test/index.test.ts | 21 ++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 core/cli/test/files/multiple-hook-options/.toolkitrc.yml diff --git a/core/cli/src/plugin/reduce-installations.ts b/core/cli/src/plugin/reduce-installations.ts index c629c3283..ca691c3c5 100644 --- a/core/cli/src/plugin/reduce-installations.ts +++ b/core/cli/src/plugin/reduce-installations.ts @@ -6,6 +6,9 @@ import { HookSchemas, HookOptions } from '@dotcom-tool-kit/schemas' import { Conflict, isConflict } from '@dotcom-tool-kit/conflict' import { groupBy } from 'lodash' +const extractForHook = (installation: HookInstallation | Conflict): string => + isConflict(installation) ? installation.conflicting[0].forHook : installation.forHook + // this function recursively collects all the hook installation requests from all plugins, // and merges them into a single, flat array of HookInstallation objects and/or Conflicts. // @@ -46,15 +49,13 @@ export async function reducePluginHookInstallations( (plugin.children ?? []).map((child) => reducePluginHookInstallations(logger, config, hookClasses, child)) ).then((installations) => installations.flat()) - const childInstallations = Object.entries( - groupBy(rawChildInstallations, (installation) => - isConflict(installation) ? installation.conflicting[0].forHook : installation.forHook - ) - ).flatMap(([forHook, installations]) => { - const hookClass = hookClasses[forHook] + const childInstallations = Object.entries(groupBy(rawChildInstallations, extractForHook)).flatMap( + ([forHook, installations]) => { + const hookClass = hookClasses[forHook] - return hookClass.mergeChildInstallations(plugin, installations) - }) + return hookClass.mergeChildInstallations(plugin, installations) + } + ) if (plugin.rcFile.options.hooks.length === 0) { return childInstallations @@ -72,7 +73,10 @@ export async function reducePluginHookInstallations( hookConstructor: hookClass } - return hookClass.overrideChildInstallations(plugin, installation, childInstallations) + const childInstallationsForHook = childInstallations.filter( + (childInstallation) => id === extractForHook(childInstallation) + ) + return hookClass.overrideChildInstallations(plugin, installation, childInstallationsForHook) }) ) } diff --git a/core/cli/test/files/multiple-hook-options/.toolkitrc.yml b/core/cli/test/files/multiple-hook-options/.toolkitrc.yml new file mode 100644 index 000000000..2d6ea68d1 --- /dev/null +++ b/core/cli/test/files/multiple-hook-options/.toolkitrc.yml @@ -0,0 +1,12 @@ +plugins: + - '@dotcom-tool-kit/circleci' + - '@dotcom-tool-kit/package-json-hook' +options: + hooks: + - PackageJson: + scripts: + somethingcustom: 'test:local' + - CircleCi: + jobs: + - name: test + command: test:local diff --git a/core/cli/test/index.test.ts b/core/cli/test/index.test.ts index c2800ebe9..fc8223fa6 100644 --- a/core/cli/test/index.test.ts +++ b/core/cli/test/index.test.ts @@ -6,6 +6,7 @@ import { describe, expect, it, jest } from '@jest/globals' import * as path from 'path' import winston, { Logger } from 'winston' import { createConfig, validateConfig } from '../src/config' +import { loadHookInstallations } from '../src/install' import { loadPlugin, resolvePlugin, resolvePluginOptions } from '../src/plugin' import { validatePlugins } from '../src/config/validate-plugins' @@ -121,4 +122,24 @@ describe('cli', () => { throw e } }) + + it('should successfully install when options for different hooks are defined', async () => { + const config = createConfig() + + const plugin = await loadPlugin('app root', config, logger, { + id: 'reolved test root', + root: path.join(__dirname, 'files/multiple-hook-options') + }) + expect(plugin.valid).toBe(true) + + const validatedPluginConfig = validatePlugins(config) + expect(validatedPluginConfig.valid).toBe(true) + const validPluginConfig = (validatedPluginConfig as Valid).value + + resolvePlugin((plugin as Valid).value, validPluginConfig, logger) + + const validConfig = validateConfig(validPluginConfig, logger) + const hooks = await loadHookInstallations(logger, validConfig) + expect(hooks.valid).toBe(true) + }) }) From 4065b9a0bc72ba68e884ac0bbb49bc49a0628490 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 12:42:06 +0100 Subject: [PATCH 212/321] build: proof of concept script to generate some markdown from zod schema --- package-lock.json | 3953 ++++++++++++++------------------------ package.json | 4 +- scripts/generate-docs.js | 13 + 3 files changed, 1506 insertions(+), 2464 deletions(-) create mode 100644 scripts/generate-docs.js diff --git a/package-lock.json b/package-lock.json index abd4a9f38..5b512d28b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@types/superagent": "^4.1.10" }, "devDependencies": { + "@apaleslimghost/zod2md": "^0.2.0-0", "@commitlint/cli": "^16.1.0", "@commitlint/config-conventional": "^16.0.0", "@dotcom-reliability-kit/eslint-config": "^2.0.0", @@ -38,7 +39,8 @@ "prettier": "^2.8.8", "release-please": "^15.0.0", "ts-jest": "^29.1.2", - "typescript": "~5.4.5" + "typescript": "~5.4.5", + "zod2md": "^0.1.2" }, "engines": { "node": "18.x || 20.x", @@ -99,9 +101,8 @@ }, "core/cli/node_modules/@types/node": { "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "dev": true + "dev": true, + "license": "MIT" }, "core/cli/node_modules/globby": { "version": "10.0.2", @@ -123,8 +124,7 @@ }, "core/cli/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "core/cli/node_modules/yaml": { "version": "2.4.1", @@ -139,8 +139,7 @@ }, "core/cli/node_modules/zod-validation-error": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-2.1.0.tgz", - "integrity": "sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==", + "license": "MIT", "engines": { "node": ">=18.0.0" }, @@ -196,8 +195,7 @@ }, "core/create/node_modules/@aws-sdk/abort-controller": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.296.0.tgz", - "integrity": "sha512-gNUFBlBw6+sEMfDjPVa83iscpQwXBS4uoiZXnfeQ6s6tnaxqQpJDrBBmNvYqDEXNdaAJX4FhayEwkSvtir/f3A==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -208,8 +206,7 @@ }, "core/create/node_modules/@aws-sdk/client-sso": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.301.0.tgz", - "integrity": "sha512-nABoNn0O79PL72jg2oy9gR/MLmM4opZ6nQefXvXUb6RzlITZCCZ6uKkGcH2LMxOcRu6qQlY+uauX+9p0GJexlg==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -250,8 +247,7 @@ }, "core/create/node_modules/@aws-sdk/client-sso-oidc": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.301.0.tgz", - "integrity": "sha512-bCBA70/7gkrk1s1iGWt3st4p9yNIkQ3e+KV8Kx3uzRvjD0f7KltGqSNA28453tsa7ko+H/V4c7fzrJnWaQomCg==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -292,8 +288,7 @@ }, "core/create/node_modules/@aws-sdk/client-sts": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.301.0.tgz", - "integrity": "sha512-OS8wE21Lxd8aT8PMj/dusCUZKXmXaxnSI4RIO3M8w/ZPRMKkBHtzB+JXbzUcpGGxvt9mse8l6w9iLIE6XuHmig==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -338,8 +333,7 @@ }, "core/create/node_modules/@aws-sdk/config-resolver": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.300.0.tgz", - "integrity": "sha512-u3YS+XWjoHmH9wh07Lv+HueYZek/wTO8tlGvVzrlACpaS1JrALuCw8UsJUHNDack63xh9v4oMf+7c0kjuqbmtA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-config-provider": "3.295.0", @@ -352,8 +346,7 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-env": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.296.0.tgz", - "integrity": "sha512-eDWSU3p04gytkkVXnYn05YzrP5SEaj/DQiafd4y+iBl8IFfF3zM6982rs6qFhvpwrHeSbLqHNfKR1HDWVwfG5g==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -365,8 +358,7 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-imds": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.300.0.tgz", - "integrity": "sha512-l7ZFGlr4TjhS0FIt3XwuAJYNAbQ4eDsovMMUVYLDPti1NxlbQDH85xAyaDWF9dU1Gulrpfzz9Ei7q4GYFFPHnQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/node-config-provider": "3.300.0", "@aws-sdk/property-provider": "3.296.0", @@ -380,8 +372,7 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-ini": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.301.0.tgz", - "integrity": "sha512-tAsNH6vQZ7U459FzjStIXoi3HZAsl6y8CMf6364dyisZ0xiCiVHLxziTmSxntcR0560NFFSOY1WS5MrbIIneGQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.296.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -399,8 +390,7 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-node": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.301.0.tgz", - "integrity": "sha512-WNz7+HoGEkAHaOL1d4D2c/LxYS3zBdqzLs7uYgekoqTSMQhTaIMyJIJgChcklAmV/yM1+2c3lS1NEtCCz3/Vxw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.296.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -419,8 +409,7 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-process": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.300.0.tgz", - "integrity": "sha512-HGBLXupPU2XTvHmlcbSgH/zLyhQ1joLIBAvKvyxyjQTIeFSDOufDqRBY4CzNzPv0yJlvSi3gAfL36CR9dh2R4w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/shared-ini-file-loader": "3.300.0", @@ -433,8 +422,7 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-sso": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.301.0.tgz", - "integrity": "sha512-5mGoBX5WmZRuL3RIWgdhMbnKYHSmM54qEFjbtRiFXZQ1QSItom1ICBCyIEoNMZQ20+iRxyTgf/fGCJrXhDlIqQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-sso": "3.301.0", "@aws-sdk/property-provider": "3.296.0", @@ -449,8 +437,7 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-web-identity": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.296.0.tgz", - "integrity": "sha512-Rl6Ohoekxe+pccA55XXQDW5wApbg3rGWr6FkmPRcg7Ld6Vfe+HL8OtfsFf83/0eoFerevbif+00BdknXWT05LA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -462,8 +449,7 @@ }, "core/create/node_modules/@aws-sdk/fetch-http-handler": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.296.0.tgz", - "integrity": "sha512-wHuKQ+PGKQkYGVuIGscbcbbASl8yIVOSC+QTrZQ4PNsMDvQd9ey2npsmxZk1Z2ULaxY+qYtZCmByyGc8k51TtQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/querystring-builder": "3.296.0", @@ -474,8 +460,7 @@ }, "core/create/node_modules/@aws-sdk/hash-node": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.296.0.tgz", - "integrity": "sha512-01Sgxm0NE3rtEznLY8vx1bfNsIeM5Sk5SjY9RXqnvCf9EyaKH9x5FMS/DX/SgDdIYi3aXbTwiwScNVCNBzOIQA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-buffer-from": "3.295.0", @@ -488,8 +473,7 @@ }, "core/create/node_modules/@aws-sdk/invalid-dependency": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.296.0.tgz", - "integrity": "sha512-dmy4fUds0woHGjxwziaSYCLtb/SOfoEeQjW0GFvHj+YGFyY5hJzna4C759Tt8X5obh1evUXlQcH+FL7TS+7tRQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -497,8 +481,7 @@ }, "core/create/node_modules/@aws-sdk/is-array-buffer": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.295.0.tgz", - "integrity": "sha512-SCIt10cr5dud7hvwveU4wkLjvkGssJ3GrcbHCds2NwI+JHmpcaaNYLAqi305JAuT29T36U5ssTFDSmrrEOcfag==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -508,8 +491,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-content-length": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.296.0.tgz", - "integrity": "sha512-e7lJm3kkC2pWZdIw23gpMUk1GrpRTBRqhdFfVwyduXw6Wo4nBYv8Z5MOYy3/SlpjE1BDCaPBoZ3O19cO3arHxg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -521,8 +503,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-endpoint": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.299.0.tgz", - "integrity": "sha512-37BGxHem6yKjSC6zG2xPjvjE7APIDIvwkxL+/K1Jz9+T6AZITcs7tx5y6mIfvaHsdPuCKjrl7Wzg/9jgUKuLkw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-serde": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -536,8 +517,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-host-header": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.296.0.tgz", - "integrity": "sha512-V47dFtfkX5lXWv9GDp71gZVCRws4fEdQ9QF9BQ/2UMSNrYjQLg6mFe7NibH+IJoNOid2FIwWIl94Eos636VGYQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -549,8 +529,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-logger": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.296.0.tgz", - "integrity": "sha512-LzfEEFyBR9LXdWwLdtBrmi1vLdzgdJNntEgzqktVF8LwaCyY+9xIE6TGu/2V+9fJHAwECxjOC1eQbNQdAZ0Tmw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -561,8 +540,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-recursion-detection": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.296.0.tgz", - "integrity": "sha512-UG7TLDPz9ImQG0uVklHTxE9Us7rTImwN+6el6qZCpoTBuGeXgOkfb0/p8izJyFgY/hMUR4cZqs7IdCDUkxQF3w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -574,8 +552,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-retry": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.300.0.tgz", - "integrity": "sha512-c3tj0Uc64mqnsosAjRBQbit0EUOd0OKrqC5eDB3YCJyLWQSlYRBk4ZBBbN2qTfo3ZCDP+tHgWxRduQlV6Knezg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/service-error-classification": "3.296.0", @@ -591,8 +568,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-sdk-sts": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.299.0.tgz", - "integrity": "sha512-yE7IiMQpF1FYqLSYOei4AYM9z62ayFfMMyhKE9IFs+TVaag97uz8NaRlr88HDTcBCZ0CMl6UwNJlZytPD4NjCw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-signing": "3.299.0", "@aws-sdk/types": "3.296.0", @@ -604,8 +580,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-serde": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.296.0.tgz", - "integrity": "sha512-xk2PpWAAX758oUTGkGBAncpOr7ddIXisjD2Y2r9DDXuE4JMho2x6zcrVSiYsGIQ6MHZ9XNJKBVDiK9PA4iQWGQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -616,8 +591,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-signing": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.299.0.tgz", - "integrity": "sha512-anhrjeNuo0470QodEmzteFMnqABNebL900yhfODySXCMiaoeTBpo8Qd8t4q4O8PizA7FeLYA3l/5tb/udp7qew==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/protocol-http": "3.296.0", @@ -632,8 +606,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-stack": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.296.0.tgz", - "integrity": "sha512-Rgo7/mdk9tt4qa9+pzG3AoGNhuj7NmnF5H+3DoPm75h58BYP8hKbKobdPGgI2rZLPtO3PGgmyw/4K4tQJPIZ8g==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -643,8 +616,7 @@ }, "core/create/node_modules/@aws-sdk/middleware-user-agent": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.299.0.tgz", - "integrity": "sha512-Brm5UcbRhuVVmmbpDN8/WSJPCHogV64jGXL5upfL+iJ0c5eZ57LXOZ8kz++t3BU1rEkSIXHJanneEmn7Wbd5sA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -657,8 +629,7 @@ }, "core/create/node_modules/@aws-sdk/node-config-provider": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.300.0.tgz", - "integrity": "sha512-60XJV+eW1FyyRNT75kAGdqDHLpWWqnZeCrEyufqQ3BXhhbD1l6oHy5W573DccEO84/0gQYlNbKL8hd8+iB59vA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/shared-ini-file-loader": "3.300.0", @@ -671,8 +642,7 @@ }, "core/create/node_modules/@aws-sdk/node-http-handler": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.296.0.tgz", - "integrity": "sha512-D15jjPqYSNhEq58BwkmIpD3VwqG4bL5acAaNu5wWAI4S4236JlG+nmpi3gEeE25z1KCwtBl7G30fVRgXYJ2CWA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/abort-controller": "3.296.0", "@aws-sdk/protocol-http": "3.296.0", @@ -686,8 +656,7 @@ }, "core/create/node_modules/@aws-sdk/property-provider": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.296.0.tgz", - "integrity": "sha512-kjczxE9Od5LoAKQOmxVWISJ9oPG3aCsB+2+NdI+k9EJFDXUUdMcVV3Skei5uHGgKLMsI6CZy8ezZx6YxOSLSew==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -698,8 +667,7 @@ }, "core/create/node_modules/@aws-sdk/protocol-http": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.296.0.tgz", - "integrity": "sha512-0U1Z/+tpwdRiSToWo1bpdkbTzjbLugTnd02ATjvK4B7zi363SUGlKfoWgV+v7FU/22CIUI1ZIe7XzXvq5rJfjA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -710,8 +678,7 @@ }, "core/create/node_modules/@aws-sdk/querystring-builder": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.296.0.tgz", - "integrity": "sha512-+ZrZdTRaVI1R1xKQNrTwuiRoPateUaJ/DNw/myJpTPt+ZRg0H7LKBGaJYwL4pl5l/z1UM/E1fOttSfSW7GHxfw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-uri-escape": "3.295.0", @@ -723,8 +690,7 @@ }, "core/create/node_modules/@aws-sdk/querystring-parser": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.296.0.tgz", - "integrity": "sha512-nLNZKVQfK42euv7101cE5qfg17YCtGcfccx3B5XSAzvyTROR46kwYqbEvYSsWisbZoRhbQc905gB/5E0U5HDIw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -735,16 +701,14 @@ }, "core/create/node_modules/@aws-sdk/service-error-classification": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.296.0.tgz", - "integrity": "sha512-YIsWSQ38e1+FqXz3CMrkKS0JD8OLlHf6I72PJhbfegePpQQFqi9R8OREjP5V7UR9Z972yruv4i96ROH6SCtmoA==", + "license": "Apache-2.0", "engines": { "node": ">=14.0.0" } }, "core/create/node_modules/@aws-sdk/shared-ini-file-loader": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.300.0.tgz", - "integrity": "sha512-xA+V08AMsb1EcNJ2UF896T4I3f6Q/H56Z3gTwcXyFXsCY3lYkEB2MEdST+x4+20emELkYjtu5SNsGgUCBehR7g==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -755,8 +719,7 @@ }, "core/create/node_modules/@aws-sdk/signature-v4": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.299.0.tgz", - "integrity": "sha512-3TtP+S3Tu0Q2/EwJLnN+IEok9nRyez79f6vprqXbC9Lex623cqh/OOYSy2oUjFlIgsIOLPum87/1bfcznYW+yQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/is-array-buffer": "3.295.0", "@aws-sdk/types": "3.296.0", @@ -772,8 +735,7 @@ }, "core/create/node_modules/@aws-sdk/smithy-client": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.296.0.tgz", - "integrity": "sha512-HEpsLNozGe9XOWouq5A1TFw5KhFodi8tZqYVNEbSpLoRR+EQKf6OCRvKIRkOn7FnnaOasOR1n7S0D51UG6/irw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-stack": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -785,8 +747,7 @@ }, "core/create/node_modules/@aws-sdk/token-providers": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.301.0.tgz", - "integrity": "sha512-TgchzkIOLGMhL3dFKGHyztZ4/HOM/WvJC0bRxvrWTs+iDHRaaKNpzW1RzCVCtbH8F/B9h5qPdRFJ6jTHtCKf4A==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-sso-oidc": "3.301.0", "@aws-sdk/property-provider": "3.296.0", @@ -800,8 +761,7 @@ }, "core/create/node_modules/@aws-sdk/types": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.296.0.tgz", - "integrity": "sha512-s0wIac64rrMEo2ioUxP9IarGiiCGmelCspNcoNTPSjGl25QqjhyfQqTeGgS58qJ4fHoQb07qra39930xp1IzJg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -811,8 +771,7 @@ }, "core/create/node_modules/@aws-sdk/url-parser": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.296.0.tgz", - "integrity": "sha512-nBgeGF+ziuDSLz+y8UAl6zL2tXxDwh3wqeXFe9ZcR4YW71BWuh+vEqEsaEMutOrfnJacCrYKTs9TkIOW41cEGg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/querystring-parser": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -821,8 +780,7 @@ }, "core/create/node_modules/@aws-sdk/util-base64": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.295.0.tgz", - "integrity": "sha512-z1r40BsBiOTALnzASvLb4qutGwPpL+jH2UKTCV5WJLXZFMzRnpZaRfeZGE8lMJ/i0+jv9H9G1FmVzE8UgB4rhw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/util-buffer-from": "3.295.0", "tslib": "^2.5.0" @@ -833,16 +791,14 @@ }, "core/create/node_modules/@aws-sdk/util-body-length-browser": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.295.0.tgz", - "integrity": "sha512-NbG4/RSHV1VueStPRclSo5zRjNUmcDlNAs29sniZF+YaN0+Ad7hEdu/YgJw39shBfUaurz2Wv0pufU3cxE5Tng==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" } }, "core/create/node_modules/@aws-sdk/util-body-length-node": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.295.0.tgz", - "integrity": "sha512-dvGf8VBmrT66lM0n6P/h7wnlHS4Atafyivyl8f4TUCMvRdpqryvvrtnX6yYcq3T7VKQmas/2SOlgDvcrhGXaiw==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -852,8 +808,7 @@ }, "core/create/node_modules/@aws-sdk/util-buffer-from": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.295.0.tgz", - "integrity": "sha512-5ezVEITQnrQKn+CU9qfZHgRp2nrrbX0Clmlm9aiNjAEQEPHY33tWl0t6n8h8yU+IpGiNRMWBVC4aSJaE5NA1mA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/is-array-buffer": "3.295.0", "tslib": "^2.5.0" @@ -864,8 +819,7 @@ }, "core/create/node_modules/@aws-sdk/util-config-provider": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.295.0.tgz", - "integrity": "sha512-/5Dl1aV2yI8YQjqwmg4RTnl/E9NmNsx7HIwBZt+dTcOrM0LMUwczQBFFcLyqCj/qv5y+VsvLoAAA/OiBT7hb3w==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -875,8 +829,7 @@ }, "core/create/node_modules/@aws-sdk/util-defaults-mode-browser": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.296.0.tgz", - "integrity": "sha512-R+nzc0PuTMaOG3LV4FoS5W7oMAqqr8G1IyI+A4Q5iem6YDMF157qV5h6wpIt3A8n9YfjyssLsAT/WPfyv/M79w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -889,8 +842,7 @@ }, "core/create/node_modules/@aws-sdk/util-defaults-mode-node": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.300.0.tgz", - "integrity": "sha512-a8tZsgkMBhnBlADyhDXMglFh6vkX6zXcJ4pnE9D3JrLDL0Fl50/Zk8FbePilEF2Dv7XRIOe4K70OZnNeeELJcg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/config-resolver": "3.300.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -905,8 +857,7 @@ }, "core/create/node_modules/@aws-sdk/util-endpoints": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.296.0.tgz", - "integrity": "sha512-YraGGLJepXM6HCTaqEGTFf8RFRBdJ0C6uG5k0kVhiXmYxBkeupn8J07CVp9jfWqcPYWElAnMGVEZKU1OjRo4HQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -917,8 +868,7 @@ }, "core/create/node_modules/@aws-sdk/util-hex-encoding": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.295.0.tgz", - "integrity": "sha512-XJcoVo41kHzhe28PBm/rqt5mdCp8R6abwiW9ug1dA6FOoPUO8kBUxDv6xaOmA2hfRvd2ocFfBXaUCBqUowkGcQ==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -928,8 +878,7 @@ }, "core/create/node_modules/@aws-sdk/util-middleware": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.296.0.tgz", - "integrity": "sha512-MNWU+doVuX+mIehEManP6OP+f08T33qQpHoBqKIeKpn3TjZjMHG7ujACTkJiEOHUrnwTov7h0Sm+3OZwk3kh9w==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -939,8 +888,7 @@ }, "core/create/node_modules/@aws-sdk/util-retry": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.296.0.tgz", - "integrity": "sha512-0mh7SqOMjuJ4vE423SzA/AfCLM68jykbfpEBkTmfqkpjkeQSW+UXHAUdXsMmfzIneiq7go5Z548F868C3cZnwQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/service-error-classification": "3.296.0", "tslib": "^2.5.0" @@ -951,8 +899,7 @@ }, "core/create/node_modules/@aws-sdk/util-uri-escape": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.295.0.tgz", - "integrity": "sha512-1H5DcyIoXF8XcPBWf7wzHt0l+TW2EoR8Oq4gsVrPTQkHMTVclC2Yn8EF3gc4arwVBzwLulI9LMBE2L8fexGfTQ==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -962,8 +909,7 @@ }, "core/create/node_modules/@aws-sdk/util-user-agent-browser": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.299.0.tgz", - "integrity": "sha512-TRPAemTDzqxCxbpVkXV+Sp9JbEo0JdT/W8qzP/uuOdglZlNXM+SadkOuNFmqr2KG83bJE6lvomGJcJb9vMN4XQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "bowser": "^2.11.0", @@ -972,8 +918,7 @@ }, "core/create/node_modules/@aws-sdk/util-user-agent-node": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.300.0.tgz", - "integrity": "sha512-lBx4HxyTxxQiqGcmvOK4p09XC2YxmH6ANQXdXdiT28qM3OJjf5WLyl4FfdH7grDSryTFdF06FRFtJDFSuSWYrw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/node-config-provider": "3.300.0", "@aws-sdk/types": "3.296.0", @@ -993,8 +938,7 @@ }, "core/create/node_modules/@aws-sdk/util-utf8": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.295.0.tgz", - "integrity": "sha512-ITN8v3F63ZkA4sdmCtSbS/mhav4F0MEAiXDAUXtMJLNqVtaVcyQST4i9vNmPpIVthAPAtP0QjyF2tq/Di8bxtQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/util-buffer-from": "3.295.0", "tslib": "^2.5.0" @@ -1005,14 +949,12 @@ }, "core/create/node_modules/@types/node": { "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "core/create/node_modules/code-suggester": { "version": "4.3.1", - "resolved": "https://registry.npmjs.org/code-suggester/-/code-suggester-4.3.1.tgz", - "integrity": "sha512-QVW9uSIMl/KLF9yrjm2wm1h/o3j2WgGnQTH+o2+okVFlhopcJGW2Jv+CwvGGgfoSTxkcG3hocQee4ZZhdMhcew==", + "license": "Apache-2.0", "dependencies": { "@octokit/rest": "^19.0.5", "@types/yargs": "^16.0.0", @@ -1031,8 +973,7 @@ }, "core/create/node_modules/fast-xml-parser": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.1.2.tgz", - "integrity": "sha512-CDYeykkle1LiA/uqQyNwYpFbyF6Axec6YapmpUP+/RHWIoR1zKjocdvNaTsxCxZzQ6v9MLXaSYm9Qq0thv0DHg==", + "license": "MIT", "dependencies": { "strnum": "^1.0.5" }, @@ -1046,19 +987,16 @@ }, "core/create/node_modules/parse-diff": { "version": "0.11.1", - "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.11.1.tgz", - "integrity": "sha512-Oq4j8LAOPOcssanQkIjxosjATBIEJhCxMCxPhMu+Ci4wdNmAEdx0O+a7gzbR2PyKXgKPvRLIN5g224+dJAsKHA==" + "license": "MIT" }, "core/create/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "core/create/node_modules/type-fest": { "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=14.16" }, @@ -1068,24 +1006,21 @@ }, "core/create/node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "core/create/node_modules/yaml": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "license": "ISC", "engines": { "node": ">= 14" } }, "core/create/node_modules/yargs": { "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -1101,7 +1036,6 @@ }, "core/sandbox": { "version": "1.0.0", - "extraneous": true, "license": "ISC", "dependencies": { "@dotcom-tool-kit/base": "file:../../lib/base", @@ -1130,19 +1064,9 @@ "zod": "^3.22.4" } }, - "lib/base/node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, "lib/base/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -1152,8 +1076,7 @@ }, "lib/base/node_modules/semver": { "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1164,46 +1087,9 @@ "node": ">=10" } }, - "lib/base/node_modules/winston": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz", - "integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==", - "dev": true, - "dependencies": { - "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.4.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.7.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "lib/base/node_modules/winston-transport": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", - "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", - "dev": true, - "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, "lib/base/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "lib/config": { "name": "@dotcom-tool-kit/config", @@ -1247,8 +1133,7 @@ }, "lib/doppler/node_modules/tslib": { "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" + "license": "0BSD" }, "lib/error": { "name": "@dotcom-tool-kit/error", @@ -1264,8 +1149,7 @@ }, "lib/error/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "lib/logger": { "name": "@dotcom-tool-kit/logger", @@ -1291,8 +1175,7 @@ }, "lib/logger/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "lib/options": { "name": "@dotcom-tool-kit/options", @@ -1309,28 +1192,7 @@ }, "lib/options/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, - "lib/package-json-hook": { - "name": "@dotcom-tool-kit/package-json-hook", - "version": "4.2.0", - "extraneous": true, - "license": "ISC", - "dependencies": { - "@financial-times/package-json": "^3.0.0", - "lodash": "^4.17.21", - "tslib": "^2.3.1" - }, - "devDependencies": { - "@jest/globals": "^27.4.6", - "@types/lodash": "^4.14.185", - "winston": "^3.5.1" - }, - "engines": { - "node": "16.x || 18.x || 20.x", - "npm": "7.x || 8.x || 9.x || 10.x" - } + "license": "0BSD" }, "lib/plugin": { "name": "@dotcom-tool-kit/plugin", @@ -1351,51 +1213,6 @@ "zod": "^3.22.4" } }, - "lib/schemas/node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "lib/schemas/node_modules/winston": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz", - "integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==", - "dev": true, - "dependencies": { - "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.4.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.7.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "lib/schemas/node_modules/winston-transport": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", - "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", - "dev": true, - "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, "lib/state": { "name": "@dotcom-tool-kit/state", "version": "3.3.0", @@ -1410,74 +1227,197 @@ }, "lib/state/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, - "lib/types": { - "name": "@dotcom-tool-kit/types", - "version": "3.6.0", - "extraneous": true, + "lib/validated": { + "name": "@dotcom-tool-kit/validated", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/error": "^3.1.0" + } + }, + "lib/vault": { + "name": "@dotcom-tool-kit/vault", + "version": "3.2.0", "license": "ISC", "dependencies": { - "@dotcom-tool-kit/conflict": "^1.0.0", "@dotcom-tool-kit/error": "^3.2.0", - "@dotcom-tool-kit/logger": "^3.4.0", - "@dotcom-tool-kit/validated": "^1.0.0", - "semver": "^7.3.7", + "@dotcom-tool-kit/options": "^3.2.0", + "@financial-times/n-fetch": "^1.0.0", + "fs": "0.0.1-security", + "os": "^0.1.2", + "path": "^0.12.7", + "superagent": "^6.1.0", "tslib": "^2.3.1" }, "devDependencies": { "@dotcom-tool-kit/schemas": "^1.0.0", - "@jest/globals": "^27.4.6", - "@types/prompts": "^2.0.14", - "@types/semver": "^7.3.9", - "winston": "^3.5.1", - "zod": "^3.22.4" + "@types/jest": "^27.0.2", + "winston": "^3.5.1" }, "engines": { - "node": "16.x || 18.x || 20.x", + "node": "18.x || 20.x", "npm": "7.x || 8.x || 9.x || 10.x" + } + }, + "lib/vault/node_modules/@dotcom-reliability-kit/app-info": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/app-info/-/app-info-2.3.0.tgz", + "integrity": "sha512-LMyL1tmNOl5aRtBih4EewqXEUK8oOF7j4sa8WCnDUdVlJedUl09iZrBk5th20qvgk2DzO0b5XwKVPLsVWvutCg==", + "engines": { + "node": "16.x || 18.x || 20.x", + "npm": "7.x || 8.x || 9.x" + } + }, + "lib/vault/node_modules/@dotcom-reliability-kit/logger": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/logger/-/logger-2.4.2.tgz", + "integrity": "sha512-Gv5mist7h61Ostagp08KnyyCn25FgzSKRdpIPRTbd412pci8i3rHLwADHUROfDjvNX/bVRBd0sda9RCbkF6aIA==", + "dependencies": { + "@dotcom-reliability-kit/app-info": "^2.3.0", + "@dotcom-reliability-kit/serialize-error": "^2.2.1", + "lodash.clonedeep": "^4.5.0", + "pino": "^8.17.1" + }, + "engines": { + "node": "16.x || 18.x || 20.x", + "npm": "7.x || 8.x || 9.x" }, "peerDependencies": { - "zod": "^3.22.4" + "pino-pretty": ">=7.0.0 <11.0.0" } }, - "lib/validated": { - "name": "@dotcom-tool-kit/validated", - "version": "1.0.0", - "license": "ISC", + "lib/vault/node_modules/@dotcom-reliability-kit/serialize-error": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/serialize-error/-/serialize-error-2.2.1.tgz", + "integrity": "sha512-JP8skyGR3YcCo2tTZogYoLUPWrs5Se+d07MZfBeCXMb2+2BmM79/3V8B6HJ8jPFq6/f6nVVFbQ7VpgHnNk6T2Q==", + "engines": { + "node": "16.x || 18.x || 20.x", + "npm": "7.x || 8.x || 9.x" + } + }, + "lib/vault/node_modules/@financial-times/n-fetch": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@financial-times/n-fetch/-/n-fetch-1.0.1.tgz", + "integrity": "sha512-LG0F/8V3gQe1D2/0WuHNYFIB/D9w5RIgstZbcqqpF+jqODIWBN6LY2isJ6qs3R+he2ev0QacuS8EupvdEpYxag==", + "deprecated": "n-fetch is no longer supported. It will get security patches up until 2024-07-01", "dependencies": { - "@dotcom-tool-kit/error": "^3.1.0" + "@dotcom-reliability-kit/logger": "^2.4.2", + "http-errors": "^2.0.0", + "node-fetch": "^2.7.0" + }, + "engines": { + "node": "16.x || 18.x", + "npm": "7.x || 8.x || 9.x" + } + }, + "lib/vault/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "lib/vault/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "lib/vault/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "lib/vault/node_modules/pino": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.20.0.tgz", + "integrity": "sha512-uhIfMj5TVp+WynVASaVEJFTncTUe4dHBq6CWplu/vBgvGHhvBvQfxz+vcOrnnBQdORH3izaGEurLfNlq3YxdFQ==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.1.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "lib/vault/node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + }, + "lib/vault/node_modules/sonic-boom": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", + "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", + "dependencies": { + "atomic-sleep": "^1.0.0" } }, - "lib/vault": { - "name": "@dotcom-tool-kit/vault", - "version": "3.2.0", - "license": "ISC", - "dependencies": { - "@dotcom-tool-kit/error": "^3.2.0", - "@dotcom-tool-kit/options": "^3.2.0", - "@financial-times/n-fetch": "^1.0.0", - "fs": "0.0.1-security", - "os": "^0.1.2", - "path": "^0.12.7", - "superagent": "^6.1.0", - "tslib": "^2.3.1" - }, - "devDependencies": { - "@dotcom-tool-kit/schemas": "^1.0.0", - "@types/jest": "^27.0.2", - "winston": "^3.5.1" - }, + "lib/vault/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": "18.x || 20.x", - "npm": "7.x || 8.x || 9.x || 10.x" + "node": ">= 0.8" } }, + "lib/vault/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "lib/vault/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" + }, + "lib/vault/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "lib/vault/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } }, "lib/wait-for-ok": { "name": "@dotcom-tool-kit/wait-for-ok", @@ -1499,14 +1439,12 @@ }, "lib/wait-for-ok/node_modules/@types/node": { "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "lib/wait-for-ok/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "node_modules/@actions/exec": { "version": "1.1.1", @@ -1532,8 +1470,7 @@ }, "node_modules/@apaleslimghost/boxen": { "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@apaleslimghost/boxen/-/boxen-5.1.3.tgz", - "integrity": "sha512-UkSSOihJUY2VKdU0WE8NH6xgB/P1iMEODkaXlRqCh5WDZ/8weZq/eHblFJM+F9CCd+QMkIbp2TjCmJB1A9rTRg==", + "license": "MIT", "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -1553,8 +1490,7 @@ }, "node_modules/@apaleslimghost/boxen/node_modules/camelcase": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -1562,10 +1498,42 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@apaleslimghost/zod2md": { + "version": "0.2.0-0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commander-js/extra-typings": "^12.0.0", + "bundle-require": "^4.0.2", + "commander": "^12.0.0", + "esbuild": "^0.19.11" + }, + "bin": { + "zod2md": "dist/bin.js" + }, + "peerDependencies": { + "zod": "^3.22.0" + } + }, + "node_modules/@apaleslimghost/zod2md/node_modules/@commander-js/extra-typings": { + "version": "12.0.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "commander": "~12.0.0" + } + }, + "node_modules/@apaleslimghost/zod2md/node_modules/commander": { + "version": "12.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@aws-crypto/crc32": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", @@ -1574,8 +1542,7 @@ }, "node_modules/@aws-crypto/crc32c": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", - "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", @@ -1584,16 +1551,14 @@ }, "node_modules/@aws-crypto/ie11-detection": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", - "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "license": "Apache-2.0", "dependencies": { "tslib": "^1.11.1" } }, "node_modules/@aws-crypto/sha1-browser": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", - "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/ie11-detection": "^3.0.0", "@aws-crypto/supports-web-crypto": "^3.0.0", @@ -1606,8 +1571,7 @@ }, "node_modules/@aws-crypto/sha256-browser": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", - "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/ie11-detection": "^3.0.0", "@aws-crypto/sha256-js": "^3.0.0", @@ -1621,8 +1585,7 @@ }, "node_modules/@aws-crypto/sha256-js": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", - "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", @@ -1631,16 +1594,14 @@ }, "node_modules/@aws-crypto/supports-web-crypto": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", - "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^1.11.1" } }, "node_modules/@aws-crypto/util": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-utf8-browser": "^3.0.0", @@ -1649,8 +1610,7 @@ }, "node_modules/@aws-sdk/abort-controller": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.257.0.tgz", - "integrity": "sha512-ekWy391lOerS0ZECdhp/c+X7AToJIpfNrCPjuj3bKr+GMQYckGsYsdbm6AUD4sxBmfvuaQmVniSXWovaxwcFcQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -1661,21 +1621,18 @@ }, "node_modules/@aws-sdk/abort-controller/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/chunked-blob-reader": { "version": "3.188.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/chunked-blob-reader/-/chunked-blob-reader-3.188.0.tgz", - "integrity": "sha512-zkPRFZZPL3eH+kH86LDYYXImiClA1/sW60zYOjse9Pgka+eDJlvBN6hcYxwDEKjcwATYiSRR1aVQHcfCinlGXg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" } }, "node_modules/@aws-sdk/chunked-blob-reader-native": { "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/chunked-blob-reader-native/-/chunked-blob-reader-native-3.208.0.tgz", - "integrity": "sha512-JeOZ95PW+fJ6bbuqPySYqLqHk1n4+4ueEEraJsiUrPBV0S1ZtyvOGHcnGztKUjr2PYNaiexmpWuvUve9K12HRA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/util-base64": "3.208.0", "tslib": "^2.3.1" @@ -1683,18 +1640,15 @@ }, "node_modules/@aws-sdk/chunked-blob-reader-native/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/chunked-blob-reader/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/client-iam": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.301.0.tgz", - "integrity": "sha512-CO8c3x7Q+BJpjZxTt8sPH2VK+8IZRn6ecc7E35GUd0gk8nUcz6Onu/h28Sn6kHkLZBQmLw3ngifkaIzDydmEew==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -1740,8 +1694,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/abort-controller": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.296.0.tgz", - "integrity": "sha512-gNUFBlBw6+sEMfDjPVa83iscpQwXBS4uoiZXnfeQ6s6tnaxqQpJDrBBmNvYqDEXNdaAJX4FhayEwkSvtir/f3A==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -1752,8 +1705,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/client-sso": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.301.0.tgz", - "integrity": "sha512-nABoNn0O79PL72jg2oy9gR/MLmM4opZ6nQefXvXUb6RzlITZCCZ6uKkGcH2LMxOcRu6qQlY+uauX+9p0GJexlg==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -1794,8 +1746,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/client-sso-oidc": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.301.0.tgz", - "integrity": "sha512-bCBA70/7gkrk1s1iGWt3st4p9yNIkQ3e+KV8Kx3uzRvjD0f7KltGqSNA28453tsa7ko+H/V4c7fzrJnWaQomCg==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -1836,8 +1787,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/client-sts": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.301.0.tgz", - "integrity": "sha512-OS8wE21Lxd8aT8PMj/dusCUZKXmXaxnSI4RIO3M8w/ZPRMKkBHtzB+JXbzUcpGGxvt9mse8l6w9iLIE6XuHmig==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -1882,8 +1832,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/config-resolver": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.300.0.tgz", - "integrity": "sha512-u3YS+XWjoHmH9wh07Lv+HueYZek/wTO8tlGvVzrlACpaS1JrALuCw8UsJUHNDack63xh9v4oMf+7c0kjuqbmtA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-config-provider": "3.295.0", @@ -1896,8 +1845,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-env": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.296.0.tgz", - "integrity": "sha512-eDWSU3p04gytkkVXnYn05YzrP5SEaj/DQiafd4y+iBl8IFfF3zM6982rs6qFhvpwrHeSbLqHNfKR1HDWVwfG5g==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -1909,8 +1857,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-imds": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.300.0.tgz", - "integrity": "sha512-l7ZFGlr4TjhS0FIt3XwuAJYNAbQ4eDsovMMUVYLDPti1NxlbQDH85xAyaDWF9dU1Gulrpfzz9Ei7q4GYFFPHnQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/node-config-provider": "3.300.0", "@aws-sdk/property-provider": "3.296.0", @@ -1924,8 +1871,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-ini": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.301.0.tgz", - "integrity": "sha512-tAsNH6vQZ7U459FzjStIXoi3HZAsl6y8CMf6364dyisZ0xiCiVHLxziTmSxntcR0560NFFSOY1WS5MrbIIneGQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.296.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -1943,8 +1889,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-node": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.301.0.tgz", - "integrity": "sha512-WNz7+HoGEkAHaOL1d4D2c/LxYS3zBdqzLs7uYgekoqTSMQhTaIMyJIJgChcklAmV/yM1+2c3lS1NEtCCz3/Vxw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.296.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -1963,8 +1908,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-process": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.300.0.tgz", - "integrity": "sha512-HGBLXupPU2XTvHmlcbSgH/zLyhQ1joLIBAvKvyxyjQTIeFSDOufDqRBY4CzNzPv0yJlvSi3gAfL36CR9dh2R4w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/shared-ini-file-loader": "3.300.0", @@ -1977,8 +1921,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-sso": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.301.0.tgz", - "integrity": "sha512-5mGoBX5WmZRuL3RIWgdhMbnKYHSmM54qEFjbtRiFXZQ1QSItom1ICBCyIEoNMZQ20+iRxyTgf/fGCJrXhDlIqQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-sso": "3.301.0", "@aws-sdk/property-provider": "3.296.0", @@ -1993,8 +1936,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-web-identity": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.296.0.tgz", - "integrity": "sha512-Rl6Ohoekxe+pccA55XXQDW5wApbg3rGWr6FkmPRcg7Ld6Vfe+HL8OtfsFf83/0eoFerevbif+00BdknXWT05LA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2006,8 +1948,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/fetch-http-handler": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.296.0.tgz", - "integrity": "sha512-wHuKQ+PGKQkYGVuIGscbcbbASl8yIVOSC+QTrZQ4PNsMDvQd9ey2npsmxZk1Z2ULaxY+qYtZCmByyGc8k51TtQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/querystring-builder": "3.296.0", @@ -2018,8 +1959,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/hash-node": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.296.0.tgz", - "integrity": "sha512-01Sgxm0NE3rtEznLY8vx1bfNsIeM5Sk5SjY9RXqnvCf9EyaKH9x5FMS/DX/SgDdIYi3aXbTwiwScNVCNBzOIQA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-buffer-from": "3.295.0", @@ -2032,8 +1972,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/invalid-dependency": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.296.0.tgz", - "integrity": "sha512-dmy4fUds0woHGjxwziaSYCLtb/SOfoEeQjW0GFvHj+YGFyY5hJzna4C759Tt8X5obh1evUXlQcH+FL7TS+7tRQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2041,8 +1980,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/is-array-buffer": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.295.0.tgz", - "integrity": "sha512-SCIt10cr5dud7hvwveU4wkLjvkGssJ3GrcbHCds2NwI+JHmpcaaNYLAqi305JAuT29T36U5ssTFDSmrrEOcfag==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -2052,8 +1990,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-content-length": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.296.0.tgz", - "integrity": "sha512-e7lJm3kkC2pWZdIw23gpMUk1GrpRTBRqhdFfVwyduXw6Wo4nBYv8Z5MOYy3/SlpjE1BDCaPBoZ3O19cO3arHxg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2065,8 +2002,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-endpoint": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.299.0.tgz", - "integrity": "sha512-37BGxHem6yKjSC6zG2xPjvjE7APIDIvwkxL+/K1Jz9+T6AZITcs7tx5y6mIfvaHsdPuCKjrl7Wzg/9jgUKuLkw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-serde": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2080,8 +2016,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-host-header": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.296.0.tgz", - "integrity": "sha512-V47dFtfkX5lXWv9GDp71gZVCRws4fEdQ9QF9BQ/2UMSNrYjQLg6mFe7NibH+IJoNOid2FIwWIl94Eos636VGYQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2093,8 +2028,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-logger": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.296.0.tgz", - "integrity": "sha512-LzfEEFyBR9LXdWwLdtBrmi1vLdzgdJNntEgzqktVF8LwaCyY+9xIE6TGu/2V+9fJHAwECxjOC1eQbNQdAZ0Tmw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2105,8 +2039,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-recursion-detection": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.296.0.tgz", - "integrity": "sha512-UG7TLDPz9ImQG0uVklHTxE9Us7rTImwN+6el6qZCpoTBuGeXgOkfb0/p8izJyFgY/hMUR4cZqs7IdCDUkxQF3w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2118,8 +2051,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-retry": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.300.0.tgz", - "integrity": "sha512-c3tj0Uc64mqnsosAjRBQbit0EUOd0OKrqC5eDB3YCJyLWQSlYRBk4ZBBbN2qTfo3ZCDP+tHgWxRduQlV6Knezg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/service-error-classification": "3.296.0", @@ -2135,8 +2067,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-sdk-sts": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.299.0.tgz", - "integrity": "sha512-yE7IiMQpF1FYqLSYOei4AYM9z62ayFfMMyhKE9IFs+TVaag97uz8NaRlr88HDTcBCZ0CMl6UwNJlZytPD4NjCw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-signing": "3.299.0", "@aws-sdk/types": "3.296.0", @@ -2148,8 +2079,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-serde": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.296.0.tgz", - "integrity": "sha512-xk2PpWAAX758oUTGkGBAncpOr7ddIXisjD2Y2r9DDXuE4JMho2x6zcrVSiYsGIQ6MHZ9XNJKBVDiK9PA4iQWGQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2160,8 +2090,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-signing": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.299.0.tgz", - "integrity": "sha512-anhrjeNuo0470QodEmzteFMnqABNebL900yhfODySXCMiaoeTBpo8Qd8t4q4O8PizA7FeLYA3l/5tb/udp7qew==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/protocol-http": "3.296.0", @@ -2176,8 +2105,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-stack": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.296.0.tgz", - "integrity": "sha512-Rgo7/mdk9tt4qa9+pzG3AoGNhuj7NmnF5H+3DoPm75h58BYP8hKbKobdPGgI2rZLPtO3PGgmyw/4K4tQJPIZ8g==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -2187,8 +2115,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-user-agent": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.299.0.tgz", - "integrity": "sha512-Brm5UcbRhuVVmmbpDN8/WSJPCHogV64jGXL5upfL+iJ0c5eZ57LXOZ8kz++t3BU1rEkSIXHJanneEmn7Wbd5sA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2201,8 +2128,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/node-config-provider": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.300.0.tgz", - "integrity": "sha512-60XJV+eW1FyyRNT75kAGdqDHLpWWqnZeCrEyufqQ3BXhhbD1l6oHy5W573DccEO84/0gQYlNbKL8hd8+iB59vA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/shared-ini-file-loader": "3.300.0", @@ -2215,8 +2141,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/node-http-handler": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.296.0.tgz", - "integrity": "sha512-D15jjPqYSNhEq58BwkmIpD3VwqG4bL5acAaNu5wWAI4S4236JlG+nmpi3gEeE25z1KCwtBl7G30fVRgXYJ2CWA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/abort-controller": "3.296.0", "@aws-sdk/protocol-http": "3.296.0", @@ -2230,8 +2155,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/property-provider": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.296.0.tgz", - "integrity": "sha512-kjczxE9Od5LoAKQOmxVWISJ9oPG3aCsB+2+NdI+k9EJFDXUUdMcVV3Skei5uHGgKLMsI6CZy8ezZx6YxOSLSew==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2242,8 +2166,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/protocol-http": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.296.0.tgz", - "integrity": "sha512-0U1Z/+tpwdRiSToWo1bpdkbTzjbLugTnd02ATjvK4B7zi363SUGlKfoWgV+v7FU/22CIUI1ZIe7XzXvq5rJfjA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2254,8 +2177,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/querystring-builder": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.296.0.tgz", - "integrity": "sha512-+ZrZdTRaVI1R1xKQNrTwuiRoPateUaJ/DNw/myJpTPt+ZRg0H7LKBGaJYwL4pl5l/z1UM/E1fOttSfSW7GHxfw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-uri-escape": "3.295.0", @@ -2267,8 +2189,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/querystring-parser": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.296.0.tgz", - "integrity": "sha512-nLNZKVQfK42euv7101cE5qfg17YCtGcfccx3B5XSAzvyTROR46kwYqbEvYSsWisbZoRhbQc905gB/5E0U5HDIw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2279,16 +2200,14 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/service-error-classification": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.296.0.tgz", - "integrity": "sha512-YIsWSQ38e1+FqXz3CMrkKS0JD8OLlHf6I72PJhbfegePpQQFqi9R8OREjP5V7UR9Z972yruv4i96ROH6SCtmoA==", + "license": "Apache-2.0", "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/shared-ini-file-loader": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.300.0.tgz", - "integrity": "sha512-xA+V08AMsb1EcNJ2UF896T4I3f6Q/H56Z3gTwcXyFXsCY3lYkEB2MEdST+x4+20emELkYjtu5SNsGgUCBehR7g==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2299,8 +2218,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/signature-v4": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.299.0.tgz", - "integrity": "sha512-3TtP+S3Tu0Q2/EwJLnN+IEok9nRyez79f6vprqXbC9Lex623cqh/OOYSy2oUjFlIgsIOLPum87/1bfcznYW+yQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/is-array-buffer": "3.295.0", "@aws-sdk/types": "3.296.0", @@ -2316,8 +2234,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/smithy-client": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.296.0.tgz", - "integrity": "sha512-HEpsLNozGe9XOWouq5A1TFw5KhFodi8tZqYVNEbSpLoRR+EQKf6OCRvKIRkOn7FnnaOasOR1n7S0D51UG6/irw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-stack": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2329,8 +2246,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/token-providers": { "version": "3.301.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.301.0.tgz", - "integrity": "sha512-TgchzkIOLGMhL3dFKGHyztZ4/HOM/WvJC0bRxvrWTs+iDHRaaKNpzW1RzCVCtbH8F/B9h5qPdRFJ6jTHtCKf4A==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-sso-oidc": "3.301.0", "@aws-sdk/property-provider": "3.296.0", @@ -2344,8 +2260,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/types": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.296.0.tgz", - "integrity": "sha512-s0wIac64rrMEo2ioUxP9IarGiiCGmelCspNcoNTPSjGl25QqjhyfQqTeGgS58qJ4fHoQb07qra39930xp1IzJg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -2355,8 +2270,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/url-parser": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.296.0.tgz", - "integrity": "sha512-nBgeGF+ziuDSLz+y8UAl6zL2tXxDwh3wqeXFe9ZcR4YW71BWuh+vEqEsaEMutOrfnJacCrYKTs9TkIOW41cEGg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/querystring-parser": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2365,8 +2279,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-base64": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.295.0.tgz", - "integrity": "sha512-z1r40BsBiOTALnzASvLb4qutGwPpL+jH2UKTCV5WJLXZFMzRnpZaRfeZGE8lMJ/i0+jv9H9G1FmVzE8UgB4rhw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/util-buffer-from": "3.295.0", "tslib": "^2.5.0" @@ -2377,16 +2290,14 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-body-length-browser": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.295.0.tgz", - "integrity": "sha512-NbG4/RSHV1VueStPRclSo5zRjNUmcDlNAs29sniZF+YaN0+Ad7hEdu/YgJw39shBfUaurz2Wv0pufU3cxE5Tng==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-body-length-node": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.295.0.tgz", - "integrity": "sha512-dvGf8VBmrT66lM0n6P/h7wnlHS4Atafyivyl8f4TUCMvRdpqryvvrtnX6yYcq3T7VKQmas/2SOlgDvcrhGXaiw==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -2396,8 +2307,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-buffer-from": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.295.0.tgz", - "integrity": "sha512-5ezVEITQnrQKn+CU9qfZHgRp2nrrbX0Clmlm9aiNjAEQEPHY33tWl0t6n8h8yU+IpGiNRMWBVC4aSJaE5NA1mA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/is-array-buffer": "3.295.0", "tslib": "^2.5.0" @@ -2408,8 +2318,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-config-provider": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.295.0.tgz", - "integrity": "sha512-/5Dl1aV2yI8YQjqwmg4RTnl/E9NmNsx7HIwBZt+dTcOrM0LMUwczQBFFcLyqCj/qv5y+VsvLoAAA/OiBT7hb3w==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -2419,8 +2328,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-defaults-mode-browser": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.296.0.tgz", - "integrity": "sha512-R+nzc0PuTMaOG3LV4FoS5W7oMAqqr8G1IyI+A4Q5iem6YDMF157qV5h6wpIt3A8n9YfjyssLsAT/WPfyv/M79w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2433,8 +2341,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-defaults-mode-node": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.300.0.tgz", - "integrity": "sha512-a8tZsgkMBhnBlADyhDXMglFh6vkX6zXcJ4pnE9D3JrLDL0Fl50/Zk8FbePilEF2Dv7XRIOe4K70OZnNeeELJcg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/config-resolver": "3.300.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -2449,8 +2356,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-endpoints": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.296.0.tgz", - "integrity": "sha512-YraGGLJepXM6HCTaqEGTFf8RFRBdJ0C6uG5k0kVhiXmYxBkeupn8J07CVp9jfWqcPYWElAnMGVEZKU1OjRo4HQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2461,8 +2367,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-hex-encoding": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.295.0.tgz", - "integrity": "sha512-XJcoVo41kHzhe28PBm/rqt5mdCp8R6abwiW9ug1dA6FOoPUO8kBUxDv6xaOmA2hfRvd2ocFfBXaUCBqUowkGcQ==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -2472,8 +2377,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-middleware": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.296.0.tgz", - "integrity": "sha512-MNWU+doVuX+mIehEManP6OP+f08T33qQpHoBqKIeKpn3TjZjMHG7ujACTkJiEOHUrnwTov7h0Sm+3OZwk3kh9w==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -2483,8 +2387,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-retry": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.296.0.tgz", - "integrity": "sha512-0mh7SqOMjuJ4vE423SzA/AfCLM68jykbfpEBkTmfqkpjkeQSW+UXHAUdXsMmfzIneiq7go5Z548F868C3cZnwQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/service-error-classification": "3.296.0", "tslib": "^2.5.0" @@ -2495,8 +2398,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-uri-escape": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.295.0.tgz", - "integrity": "sha512-1H5DcyIoXF8XcPBWf7wzHt0l+TW2EoR8Oq4gsVrPTQkHMTVclC2Yn8EF3gc4arwVBzwLulI9LMBE2L8fexGfTQ==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.5.0" }, @@ -2506,8 +2408,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-user-agent-browser": { "version": "3.299.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.299.0.tgz", - "integrity": "sha512-TRPAemTDzqxCxbpVkXV+Sp9JbEo0JdT/W8qzP/uuOdglZlNXM+SadkOuNFmqr2KG83bJE6lvomGJcJb9vMN4XQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.296.0", "bowser": "^2.11.0", @@ -2516,8 +2417,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-user-agent-node": { "version": "3.300.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.300.0.tgz", - "integrity": "sha512-lBx4HxyTxxQiqGcmvOK4p09XC2YxmH6ANQXdXdiT28qM3OJjf5WLyl4FfdH7grDSryTFdF06FRFtJDFSuSWYrw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/node-config-provider": "3.300.0", "@aws-sdk/types": "3.296.0", @@ -2537,8 +2437,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-utf8": { "version": "3.295.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.295.0.tgz", - "integrity": "sha512-ITN8v3F63ZkA4sdmCtSbS/mhav4F0MEAiXDAUXtMJLNqVtaVcyQST4i9vNmPpIVthAPAtP0QjyF2tq/Di8bxtQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/util-buffer-from": "3.295.0", "tslib": "^2.5.0" @@ -2549,8 +2448,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-waiter": { "version": "3.296.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.296.0.tgz", - "integrity": "sha512-L57uIC74VyTjAdCH0wQqtvJtwK4+gIT/51K/BJHEqVg6C1pOwgrdT6dHC3q8b+gdOrZ6Ff/vTEfh7FZmVcPPjg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/abort-controller": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2562,8 +2460,7 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/fast-xml-parser": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.1.2.tgz", - "integrity": "sha512-CDYeykkle1LiA/uqQyNwYpFbyF6Axec6YapmpUP+/RHWIoR1zKjocdvNaTsxCxZzQ6v9MLXaSYm9Qq0thv0DHg==", + "license": "MIT", "dependencies": { "strnum": "^1.0.5" }, @@ -2577,21 +2474,18 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/client-iam/node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/@aws-sdk/client-lambda": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.264.0.tgz", - "integrity": "sha512-Z7EnWd1PveFdcSAkqpbMQO/iOBETKAs6/RV5ZfDtNmtzku2FGk02Xm76eQnkJrUNTWesEWw/am03cK2d7brBGw==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", @@ -2637,8 +2531,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sso": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.264.0.tgz", - "integrity": "sha512-p+7sYpRcdv9omnnsPhD/vOFuZ1SpfV62ZgistBK/RDsQg2W9SIWQRW1KPt7gOCQ0nwp4efntw4Sle0LjS7ykxg==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", @@ -2680,8 +2573,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sso-oidc": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.264.0.tgz", - "integrity": "sha512-82hGEbfsD4lBGIF1q8o82jTNSgBCcBpfFsvA+ltZf0bh4ChIWOi4vVvg8G+zVQN1mm/Rj8vWYO/D0tNF8OSyWw==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", @@ -2723,8 +2615,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sts": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.264.0.tgz", - "integrity": "sha512-sco1jREkDdds4Z3V19Vlu/YpBHSzeEt1KFqOPnbjFw7pSakRNzpyWmLLxOwWjwgGKt6pSF3Aw0ZOMYsAUDc5qQ==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", @@ -2770,8 +2661,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-ini": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.264.0.tgz", - "integrity": "sha512-UU5NNlfn+Go+5PLBzyTH1YE3r/pgykpE4QYFon87sCnEQnQH9xmlRTW1f1cBSQ9kivbFZd2/C2X3qhB3fe2JfA==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.257.0", @@ -2790,8 +2680,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-node": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.264.0.tgz", - "integrity": "sha512-DPzL7oawcILs5Mduim9Z8SVeJaUpaDRVbUIrBHsMBu+N7Zuqtzr+0ckHc1bEi3iYq2QUCk5pH5vpQaZYkMlbtw==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.257.0", @@ -2811,8 +2700,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-sso": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.264.0.tgz", - "integrity": "sha512-CJuAlqIIJap6LXoqimvEAnYZ7Kb5pTbiS3e+aY+fajO3OPujmQpHuiY8kOmscjwZ4ErJdEskivcTGwXph0dPZQ==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-sdk/client-sso": "3.264.0", @@ -2828,8 +2716,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-endpoint": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.264.0.tgz", - "integrity": "sha512-H9JEAug3Oo3IA2wZIplVVF6NtauCIjICXWgbNbA8Im+I2KPe0jWtOdtQv4U+tqHe9T4zIixaCM3gjUBld+FoOA==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-sdk/middleware-serde": "3.257.0", @@ -2847,8 +2734,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/smithy-client": { "version": "3.261.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.261.0.tgz", - "integrity": "sha512-j8XQEa3caZUVFVZfhJjaskw80O/tB+IXu84HMN44N7UkXaCFHirUsNjTDztJhnVXf/gKXzIqUqprfRnOvwLtIg==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-sdk/middleware-stack": "3.257.0", @@ -2861,8 +2747,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/token-providers": { "version": "3.264.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.264.0.tgz", - "integrity": "sha512-1N54FCdBJRqrwFWHUoDpGI0rKhI29Or9ZwGjjcBzKzLhz5sEF/DEhuID7h1/KKEkXdQ0+lmXOFGMMrahrMpOow==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-sdk/client-sso-oidc": "3.264.0", @@ -2877,8 +2762,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-defaults-mode-browser": { "version": "3.261.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.261.0.tgz", - "integrity": "sha512-lX3X1NfzQVV6cakepGV24uRcqevlDnQ8VgaCV8dhnw1FVThueFigyoFaUA02+uRXbV9KIbNWkEvweNtm2wvyDw==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-sdk/property-provider": "3.257.0", @@ -2892,8 +2776,7 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-defaults-mode-node": { "version": "3.261.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.261.0.tgz", - "integrity": "sha512-4AK6yu4bOmHSocUdbGoEHbNXB09UA58ON2HBHY4NxMBuFBAd9XB2tYiyhce+Cm+o+lHbS8oQnw0VZw16WMzzew==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-sdk/config-resolver": "3.259.0", @@ -2909,14 +2792,12 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "license": "0BSD", "peer": true }, "node_modules/@aws-sdk/client-s3": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.259.0.tgz", - "integrity": "sha512-yZy7oTTqPAn5H1SxbsynzVRr6kSf5hJQYl00P1dpzsAjTJmRzV4CdHwUxsBkyfUeC6u324iJi9zir1v8HHgUJw==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "3.0.0", "@aws-crypto/sha256-browser": "3.0.0", @@ -2979,13 +2860,11 @@ }, "node_modules/@aws-sdk/client-s3/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/client-sso": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.259.0.tgz", - "integrity": "sha512-TKi9Lj0zqxsrQWOZ+e4WchNDtLDz6B+ahMzYDIOFlglDPPEzbZE//PBMZCba/AAIe6U3xaUQSnni+4mNbRLg7Q==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -3026,8 +2905,7 @@ }, "node_modules/@aws-sdk/client-sso-oidc": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.259.0.tgz", - "integrity": "sha512-TKpUX55qLM35sQXx96VnB/ZcQCcBxVU/0j0wqL8Hij+blD7fy6KrGGJPORzRphmFg8Ehf1IoCivFxrQwLrjZ6A==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -3068,18 +2946,15 @@ }, "node_modules/@aws-sdk/client-sso-oidc/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/client-sso/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/client-sts": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.259.0.tgz", - "integrity": "sha512-LXqua4FoXxR30sM4BSwmPI6x0YmDTw6yQhxQQXA5hrx+YwUf8CSpa0K6Xwfv8M5+zP0uHfY1iVxx/rnT8FOEmA==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -3124,13 +2999,11 @@ }, "node_modules/@aws-sdk/client-sts/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/config-resolver": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.259.0.tgz", - "integrity": "sha512-gViMRsc4Ye6+nzJ0OYTZIT8m4glIAdtugN2Sr/t6P2iJW5X0bSL/EcbcHBgsve1lHjeGPeyzVkT7UnyGOZ5Z/A==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/signature-v4": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3144,13 +3017,11 @@ }, "node_modules/@aws-sdk/config-resolver/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-env": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.257.0.tgz", - "integrity": "sha512-GsmBi5Di6hk1JAi1iB6/LCY8o+GmlCvJoB7wuoVmXI3VxRVwptUVjuj8EtJbIrVGrF9dSuIRPCzUoSuzEzYGlg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3162,13 +3033,11 @@ }, "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-imds": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.259.0.tgz", - "integrity": "sha512-yCxoYWZAaDrCUEWxRfrpB0Mp1cFgJEMYW8T6GIb/+DQ5QLpZmorgaVD/j90QXupqFrR5tlxwuskBIkdD2E9YNg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/node-config-provider": "3.259.0", "@aws-sdk/property-provider": "3.257.0", @@ -3182,13 +3051,11 @@ }, "node_modules/@aws-sdk/credential-provider-imds/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-ini": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.259.0.tgz", - "integrity": "sha512-/sjZv+XvcSMnvDTsau0cHxMFcbz4f4ksvgu10JQ1PpcH5CPQJviDJjZRzzijcOuMZ3SOO0skyuYU6tjY18cgIg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.257.0", "@aws-sdk/credential-provider-imds": "3.259.0", @@ -3206,13 +3073,11 @@ }, "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-node": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.259.0.tgz", - "integrity": "sha512-7doM6hCPTZD0H+A7VtElLY4Ztuhg3MbjoHs00TyPZNCym7f/AKmKi9Exiw1tGgxTJkfn/SzcAWz+TyqMP078ow==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.257.0", "@aws-sdk/credential-provider-imds": "3.259.0", @@ -3231,13 +3096,11 @@ }, "node_modules/@aws-sdk/credential-provider-node/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-process": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.257.0.tgz", - "integrity": "sha512-xK8uYeNXaclaBCGrLi4z2pxPRngqLf5BM5jg2fn57zqvlL9V5gJF972FehrVBL0bfp1/laG0ZJtD2K2sapyWAw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/shared-ini-file-loader": "3.257.0", @@ -3250,13 +3113,11 @@ }, "node_modules/@aws-sdk/credential-provider-process/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-sso": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.259.0.tgz", - "integrity": "sha512-cz+8aNKxvZ8ikd0JDcB9MZredOJNRZkbco8QAM0gXfy6ziyX+23oU8+aekZljDzQR5QNRouvMz1KKmBxZLpNyg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-sso": "3.259.0", "@aws-sdk/property-provider": "3.257.0", @@ -3271,13 +3132,11 @@ }, "node_modules/@aws-sdk/credential-provider-sso/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/credential-provider-web-identity": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.257.0.tgz", - "integrity": "sha512-Cm0uvRv4JuIbD0Kp3W0J/vwjADIyCx8HoZi5yg+QIi5nilocuTQ3ajvLeuPVSvFvdy+yaxSc5FxNXquWt7Mngw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3289,13 +3148,11 @@ }, "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/eventstream-codec": { "version": "3.258.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-codec/-/eventstream-codec-3.258.0.tgz", - "integrity": "sha512-DTd6aggICXOH74tBQEliwLbeoXRbQ3uROBWYl7DdrbAemzHACDFzPCXXa9MTJMZcq3Tva8/E/3bv1fXuU/xkAA==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "3.0.0", "@aws-sdk/types": "3.257.0", @@ -3305,13 +3162,11 @@ }, "node_modules/@aws-sdk/eventstream-codec/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/eventstream-serde-browser": { "version": "3.258.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-serde-browser/-/eventstream-serde-browser-3.258.0.tgz", - "integrity": "sha512-bRcNxDrBFd0UsrLh88kwpvGDHjVupZP3gPJ5b7wseCuuWJzp56/7hNI97IywgARta91rcaf4K147VxFkSNaVlw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/eventstream-serde-universal": "3.258.0", "@aws-sdk/types": "3.257.0", @@ -3323,13 +3178,11 @@ }, "node_modules/@aws-sdk/eventstream-serde-browser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/eventstream-serde-config-resolver": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.257.0.tgz", - "integrity": "sha512-YbUETgkcFqPJmwcBozHbx3Xloh7mPk9SunNB+Ndy8egwV3L/jNZnEzZnPOtWbD10AXSuJvSbGQ8+l4FblRqZqw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3340,13 +3193,11 @@ }, "node_modules/@aws-sdk/eventstream-serde-config-resolver/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/eventstream-serde-node": { "version": "3.258.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-serde-node/-/eventstream-serde-node-3.258.0.tgz", - "integrity": "sha512-KvuitKB3fK1ZjWcB+U6d8JNv0WJtE1zvW5DXI/OabzaIR4i/LNis7469EwTsEkTqG3mV3wUa6cBA6kBSJWTVeA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/eventstream-serde-universal": "3.258.0", "@aws-sdk/types": "3.257.0", @@ -3358,13 +3209,11 @@ }, "node_modules/@aws-sdk/eventstream-serde-node/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/eventstream-serde-universal": { "version": "3.258.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-serde-universal/-/eventstream-serde-universal-3.258.0.tgz", - "integrity": "sha512-woHNrBp8YSIaf3mcRJA0SyKFnjeLX2fRudLZq9wd555Zz/U7f45AuZOpXlU66tIZiYJI1xm32VRSIYfpIwXI+A==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/eventstream-codec": "3.258.0", "@aws-sdk/types": "3.257.0", @@ -3376,13 +3225,11 @@ }, "node_modules/@aws-sdk/eventstream-serde-universal/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/fetch-http-handler": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.257.0.tgz", - "integrity": "sha512-zOF+RzQ+wfF7tq7tGUdPcqUTh3+k2f8KCVJE07A8kCopVq4nBu4NH6Eq29Tjpwdya3YlKvE+kFssuQRRRRex+Q==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/querystring-builder": "3.257.0", @@ -3393,13 +3240,11 @@ }, "node_modules/@aws-sdk/fetch-http-handler/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/hash-blob-browser": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.257.0.tgz", - "integrity": "sha512-3Nrcci3pCCc0ZILMGa/oUMq9le6nhvgCoVxFy5skYs/mQu4QnA8HcK0u4bTueW41rBj0ZW6BHLk/2SmigIkjCQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/chunked-blob-reader": "3.188.0", "@aws-sdk/chunked-blob-reader-native": "3.208.0", @@ -3409,13 +3254,11 @@ }, "node_modules/@aws-sdk/hash-blob-browser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/hash-node": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.257.0.tgz", - "integrity": "sha512-W/USUuea5Ep3OJ2U7Ve8/5KN1YsDun2WzOFUxc1PyxXP5pW6OgC15/op0e+bmWPG851clvp5S8ZuroUr3aKi3Q==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "@aws-sdk/util-buffer-from": "3.208.0", @@ -3428,13 +3271,11 @@ }, "node_modules/@aws-sdk/hash-node/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/hash-stream-node": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-stream-node/-/hash-stream-node-3.257.0.tgz", - "integrity": "sha512-A24+EI0sO+IYO78sQPY4vVx7vzToc6XAobQqowmBJ6GXXILK72d3MR3NVbm0lmcS4Dh6MVZEFQD/DCyKvj2C7g==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "@aws-sdk/util-utf8": "3.254.0", @@ -3446,13 +3287,11 @@ }, "node_modules/@aws-sdk/hash-stream-node/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/invalid-dependency": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.257.0.tgz", - "integrity": "sha512-T68SAPRNMEhpke0wlxURgogL7q0B8dfqZsSeS20BVR/lksJxLse9+pbmCDxiu1RrXoEIsEwl5rbLN+Hw8BFFYw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3460,13 +3299,11 @@ }, "node_modules/@aws-sdk/invalid-dependency/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/is-array-buffer": { "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz", - "integrity": "sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -3476,13 +3313,11 @@ }, "node_modules/@aws-sdk/is-array-buffer/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/md5-js": { "version": "3.258.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.258.0.tgz", - "integrity": "sha512-aLdZ43sEiT68p7YYPHwKsWU1WDC8Wf8UQfb4pzbvhYNgr5VxN46AtbWTKxLAqK2adKS4FnbyX2i66fINg2dHdw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "@aws-sdk/util-utf8": "3.254.0", @@ -3491,13 +3326,11 @@ }, "node_modules/@aws-sdk/md5-js/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.259.0.tgz", - "integrity": "sha512-eY4Bf7ZeiYK2c2XQ5IU0TDneEYSnZbaFk+ysgAkNmGoLKBhybXiKy7Dh8djB3uXeNtsZ+fZaazWmsU2kxf6Ntg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3511,13 +3344,11 @@ }, "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-content-length": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.257.0.tgz", - "integrity": "sha512-yiawbV2azm6QnMY1L2ypG8PDRdjOcEIvFmT0T7y0F49rfbKJOu21j1ONAoCkLrINK6kMqcD5JSQLVCoURxiTxQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3529,13 +3360,11 @@ }, "node_modules/@aws-sdk/middleware-content-length/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-endpoint": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.257.0.tgz", - "integrity": "sha512-RQNQe/jeVuWZtXXfcOm+e3qMFICY6ERsXUrbt0rjHgvajZCklcrRJgxJSCwrcS7Le3nl9azFPMAMj9L7uSK28g==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-serde": "3.257.0", "@aws-sdk/protocol-http": "3.257.0", @@ -3552,13 +3381,11 @@ }, "node_modules/@aws-sdk/middleware-endpoint/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-expect-continue": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.257.0.tgz", - "integrity": "sha512-7HSRA2Ta0fTq9Ewznp6fYG7CYOoqr5TeqEhKL1HyFb5i6YmsCiz88JKNJTllD5O7uFcd7Td/fJ66pK4JttfaaQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3570,13 +3397,11 @@ }, "node_modules/@aws-sdk/middleware-expect-continue/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-flexible-checksums": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.259.0.tgz", - "integrity": "sha512-DwY3+cWaONvzJSVYQncfX+ZnoPnLVA7LfgR0mrgcvVZJFrqCr1lJeUmJOmE2/kcOQefPfSbKB/L4BP6vg2EUMQ==", + "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "3.0.0", "@aws-crypto/crc32c": "3.0.0", @@ -3592,13 +3417,11 @@ }, "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-host-header": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.257.0.tgz", - "integrity": "sha512-gEi9AJdJfRfU8Qr6HK1hfhxTzyV3Giq4B/h7um99hIFAT/GCg9xiPvAOKPo6UeuiKEv3b7RpSL4s6cBvnJMJBA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3610,13 +3433,11 @@ }, "node_modules/@aws-sdk/middleware-host-header/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-location-constraint": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.257.0.tgz", - "integrity": "sha512-pmm5rJR5aatXG0kC0KPBxkgoNn/ePcyVIYHGMEuJXRJm3ENy569QAH9UZeMFjprp3uuAbkqItQbY3MP8TYvuYA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3627,13 +3448,11 @@ }, "node_modules/@aws-sdk/middleware-location-constraint/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-logger": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.257.0.tgz", - "integrity": "sha512-8RDXW/VbMKBsXDfcCLmROZcWKyrekyiPa3J1aIaBy0tq9o4xpGoXw/lwwIrNVvISAFslb57rteup34bfn6ta6w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3644,13 +3463,11 @@ }, "node_modules/@aws-sdk/middleware-logger/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-recursion-detection": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.257.0.tgz", - "integrity": "sha512-rUCih6zHh8k9Edf5N5Er4s508FYbwLM0MWTD2axzlj9TjLqEQ9OKED3wHaLffXSDzodd3oTAfJCLPbWQyoZ3ZQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3662,13 +3479,11 @@ }, "node_modules/@aws-sdk/middleware-recursion-detection/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-retry": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.259.0.tgz", - "integrity": "sha512-pVh1g8e84MAi7eVtWLiiiCtn82LzxOP7+LxTRHatmgIeN22yGQBZILliPDJypUPvDYlwxI1ekiK+oPTcte0Uww==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/service-error-classification": "3.257.0", @@ -3684,21 +3499,18 @@ }, "node_modules/@aws-sdk/middleware-retry/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-retry/node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/@aws-sdk/middleware-sdk-s3": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.257.0.tgz", - "integrity": "sha512-l9KRlUgsDKV1MB3zfttX/syhIBsG5Z3VVslz6EW09eSqZVreCudW3TMdyeLemup57xC2veEpkgVj8igiXd/LVQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3711,13 +3523,11 @@ }, "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-sdk-sts": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.257.0.tgz", - "integrity": "sha512-d6IJCLRi3O2tm4AFK60WNhIwmMmspj1WzKR1q1TaoPzoREPG2xg+Am18wZBRkCyYuRPPrbizmkvAmAJiUolMAw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-signing": "3.257.0", "@aws-sdk/property-provider": "3.257.0", @@ -3732,13 +3542,11 @@ }, "node_modules/@aws-sdk/middleware-sdk-sts/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-serde": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.257.0.tgz", - "integrity": "sha512-/JasfXPWFq24mnCrx9fxW/ISBSp07RJwhsF14qzm8Qy3Z0z470C+QRM6otTwAkYuuVt1wuLjja5agq3Jtzq7dQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3749,13 +3557,11 @@ }, "node_modules/@aws-sdk/middleware-serde/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-signing": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.257.0.tgz", - "integrity": "sha512-hCH3D83LHmm6nqmtNrGTWZCVjsQXrGHIXbd17/qrw7aPFvcAhsiiCncGFP+XsUXEKa2ZqcSNMUyPrx69ofNRZQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/protocol-http": "3.257.0", @@ -3770,13 +3576,11 @@ }, "node_modules/@aws-sdk/middleware-signing/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-ssec": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.257.0.tgz", - "integrity": "sha512-YcZrKeZk/0bsFvnTqp2rcF+6BSmeLTA65ZtyNNP2hh7Imaxg3kAQcueOJBeK4YP/5nU7a1mtt/4Q8BqbIjc41g==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3787,13 +3591,11 @@ }, "node_modules/@aws-sdk/middleware-ssec/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-stack": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.257.0.tgz", - "integrity": "sha512-awg2F0SvwACBaw4HIObK8pQGfSqAc4Vy+YFzWSfZNVC35oRO6RsRdKHVU99lRC0LrT2Ptmfghl2DMPSrRDbvlQ==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -3803,13 +3605,11 @@ }, "node_modules/@aws-sdk/middleware-stack/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/middleware-user-agent": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.257.0.tgz", - "integrity": "sha512-37rt75LZyD0UWpbcFuxEGqwF3DZKSixQPl7AsDe6q3KtrO5gGQB+diH5vbY0txNNYyv5IK9WMwvY73mVmoWRmw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3821,13 +3621,11 @@ }, "node_modules/@aws-sdk/middleware-user-agent/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/node-config-provider": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.259.0.tgz", - "integrity": "sha512-DUOqr71oonBvM6yKPdhDBmraqgXHCFrVWFw7hc5ZNxL2wS/EsbKfGPJp+C+SUgpn1upIWPNnh/bNoLAbBkcLsA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/shared-ini-file-loader": "3.257.0", @@ -3840,13 +3638,11 @@ }, "node_modules/@aws-sdk/node-config-provider/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/node-http-handler": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.257.0.tgz", - "integrity": "sha512-8KnWHVVwaGKyTlkTU9BSOAiSovNDoagxemU2l10QqBbzUCVpljCUMUkABEGRJ1yoQCl6DJ7RtNkAyZ8Ne/E15A==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/abort-controller": "3.257.0", "@aws-sdk/protocol-http": "3.257.0", @@ -3860,13 +3656,11 @@ }, "node_modules/@aws-sdk/node-http-handler/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/property-provider": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.257.0.tgz", - "integrity": "sha512-3rUbRAcF0GZ5PhDiXhS4yREfZ5hOEtvYEa9S/19OdM5eoypOaLU5XnFcCKfnccSP8SkdgpJujzxOMRWNWadlAQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3877,13 +3671,11 @@ }, "node_modules/@aws-sdk/property-provider/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/protocol-http": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.257.0.tgz", - "integrity": "sha512-xt7LGOgZIvbLS3418AYQLacOqx+mo5j4mPiIMz7f6AaUg+/fBUgESVsncKDqxbEJVwwCXSka8Ca0cntJmoeMSw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3894,13 +3686,11 @@ }, "node_modules/@aws-sdk/protocol-http/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/querystring-builder": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.257.0.tgz", - "integrity": "sha512-mZHWLP7XIkzx1GIXO5WfX/iJ+aY9TWs02RE9FkdL2+by0HEMR65L3brQTbU1mIBJ7BjaPwYH24dljUOSABX7yg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "@aws-sdk/util-uri-escape": "3.201.0", @@ -3912,13 +3702,11 @@ }, "node_modules/@aws-sdk/querystring-builder/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/querystring-parser": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.257.0.tgz", - "integrity": "sha512-UDrE1dEwWrWT8dG2VCrGYrPxCWOkZ1fPTPkjpkR4KZEdQDZBqU5gYZF2xPj8Nz7pjQVHFuW2wFm3XYEk56GEjg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3929,21 +3717,18 @@ }, "node_modules/@aws-sdk/querystring-parser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/service-error-classification": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.257.0.tgz", - "integrity": "sha512-FAyR0XsueGkkqDtkP03cTJQk52NdQ9sZelLynmmlGPUP75LApRPvFe1riKrou6+LsDbwVNVffj6mbDfIcOhaOw==", + "license": "Apache-2.0", "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/shared-ini-file-loader": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.257.0.tgz", - "integrity": "sha512-HNjC1+Wx3xHiJc+CP14GhIdVhfQGSjroAsWseRxAhONocA9Fl1ZX4hx7+sA5c9nOoMVOovi6ivJ/6lCRPTDRrQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3954,13 +3739,11 @@ }, "node_modules/@aws-sdk/shared-ini-file-loader/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/signature-v4": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.257.0.tgz", - "integrity": "sha512-aLQQN59X/D0+ShzPD3Anj5ntdMA/RFeNLOUCDyDvremViGi6yxUS98usQ/8bG5Rq0sW2GGMdbFUFmrDvqdiqEQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/is-array-buffer": "3.201.0", "@aws-sdk/types": "3.257.0", @@ -3976,8 +3759,7 @@ }, "node_modules/@aws-sdk/signature-v4-multi-region": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.257.0.tgz", - "integrity": "sha512-4ZyJp6my6F6R8jG+zlIR+Sw3W2vZcBTcpzAnSAHI0UBWjx5/buiKU5QY7oj29H3pESDD7DovZinD7TtHvMNoZw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/signature-v4": "3.257.0", @@ -3999,18 +3781,15 @@ }, "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/signature-v4/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/smithy-client": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.257.0.tgz", - "integrity": "sha512-Vy/en+llpslHG6WZ2yuN+On6u7p2hROEURwAST/lpReAwBETjbsxylkWvP8maeGKQ54u9uC6lIZAOJut2I3INw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/middleware-stack": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4022,13 +3801,11 @@ }, "node_modules/@aws-sdk/smithy-client/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/token-providers": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.259.0.tgz", - "integrity": "sha512-61lbk+vjlHBtNK7ZOTdR0rgk9dQ6++tklHpXZY3AQWAl3xx6K4y00HsyAtcP6k24s8B356QwXlrQJrQY5nnkQQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-sso-oidc": "3.259.0", "@aws-sdk/property-provider": "3.257.0", @@ -4042,13 +3819,11 @@ }, "node_modules/@aws-sdk/token-providers/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/types": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.257.0.tgz", - "integrity": "sha512-LmqXuBQBGeaGi/3Rp7XiEX1B5IPO2UUfBVvu0wwGqVsmstT0SbOVDZGPmxygACbm64n+PRx3uTSDefRfoiWYZg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4058,13 +3833,11 @@ }, "node_modules/@aws-sdk/types/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/url-parser": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.257.0.tgz", - "integrity": "sha512-Qe/AcFe/NFZHa6cN2afXEQn9ehXxh57dWGdRjfjd2lQqNV4WW1R2pl2Tm1ZJ1dwuCNLJi4NHLMk8lrD3QQ8rdg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/querystring-parser": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4073,13 +3846,11 @@ }, "node_modules/@aws-sdk/url-parser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-arn-parser": { "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.208.0.tgz", - "integrity": "sha512-QV4af+kscova9dv4VuHOgH8wEr/IIYHDGcnyVtkUEqahCejWr1Kuk+SBK0xMwnZY5LSycOtQ8aeqHOn9qOjZtA==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4089,13 +3860,11 @@ }, "node_modules/@aws-sdk/util-arn-parser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-base64": { "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz", - "integrity": "sha512-PQniZph5A6N7uuEOQi+1hnMz/FSOK/8kMFyFO+4DgA1dZ5pcKcn5wiFwHkcTb/BsgVqQa3Jx0VHNnvhlS8JyTg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/util-buffer-from": "3.208.0", "tslib": "^2.3.1" @@ -4106,26 +3875,22 @@ }, "node_modules/@aws-sdk/util-base64/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-body-length-browser": { "version": "3.188.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz", - "integrity": "sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" } }, "node_modules/@aws-sdk/util-body-length-browser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-body-length-node": { "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz", - "integrity": "sha512-3zj50e5g7t/MQf53SsuuSf0hEELzMtD8RX8C76f12OSRo2Bca4FLLYHe0TZbxcfQHom8/hOaeZEyTyMogMglqg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4135,13 +3900,11 @@ }, "node_modules/@aws-sdk/util-body-length-node/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-buffer-from": { "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz", - "integrity": "sha512-7L0XUixNEFcLUGPeBF35enCvB9Xl+K6SQsmbrPk1P3mlV9mguWSDQqbOBwY1Ir0OVbD6H/ZOQU7hI/9RtRI0Zw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/is-array-buffer": "3.201.0", "tslib": "^2.3.1" @@ -4152,13 +3915,11 @@ }, "node_modules/@aws-sdk/util-buffer-from/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-config-provider": { "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz", - "integrity": "sha512-DSRqwrERUsT34ug+anlMBIFooBEGwM8GejC7q00Y/9IPrQy50KnG5PW2NiTjuLKNi7pdEOlwTSEocJE15eDZIg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4168,13 +3929,11 @@ }, "node_modules/@aws-sdk/util-config-provider/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-defaults-mode-browser": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.257.0.tgz", - "integrity": "sha512-nkfK+MNacVd3Px/fcAvU0hDeh+r7d+RLLt3sJ5Zc0gGd+i3OQEP58V8QzR9PYMvUvSvGQP16fQVQHSbRZtuWyQ==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4187,13 +3946,11 @@ }, "node_modules/@aws-sdk/util-defaults-mode-browser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-defaults-mode-node": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.259.0.tgz", - "integrity": "sha512-wRiiwT7ayIcTYGHUg/Ho9UN/Kd4V37OAxP2IbkG9rPZJNuvtKopQJhUSMDERXaMQ47dG5US8G4YVYJIEO4cKgw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/config-resolver": "3.259.0", "@aws-sdk/credential-provider-imds": "3.259.0", @@ -4208,13 +3965,11 @@ }, "node_modules/@aws-sdk/util-defaults-mode-node/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-endpoints": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.257.0.tgz", - "integrity": "sha512-3bvmRn5XGYzPPWjLuvHBKdJOb+fijnb8Ungu9bfXnTYFsng/ndHUWeHC22O/p8w3OWoRYUIMaZHxdxe27BFozg==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -4225,13 +3980,11 @@ }, "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-hex-encoding": { "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz", - "integrity": "sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4241,13 +3994,11 @@ }, "node_modules/@aws-sdk/util-hex-encoding/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-locate-window": { "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.208.0.tgz", - "integrity": "sha512-iua1A2+P7JJEDHVgvXrRJSvsnzG7stYSGQnBVphIUlemwl6nN5D+QrgbjECtrbxRz8asYFHSzhdhECqN+tFiBg==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4257,13 +4008,11 @@ }, "node_modules/@aws-sdk/util-locate-window/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-middleware": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.257.0.tgz", - "integrity": "sha512-F9ieon8B8eGVs5tyZtAIG3DZEObDvujkspho0qRbUTHUosM0ylJLsMU800fmC/uRHLRrZvb/RSp59+kNDwSAMw==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4273,13 +4022,11 @@ }, "node_modules/@aws-sdk/util-middleware/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-retry": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.257.0.tgz", - "integrity": "sha512-l9TOsOAYtZxwW3q5fQKW4rsD9t2HVaBfQ4zBamHkNTfB4vBVvCnz4oxkvSvA2MlxCA6am+K1K/oj917Tpqk53g==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/service-error-classification": "3.257.0", "tslib": "^2.3.1" @@ -4290,13 +4037,11 @@ }, "node_modules/@aws-sdk/util-retry/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-stream-browser": { "version": "3.258.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-stream-browser/-/util-stream-browser-3.258.0.tgz", - "integrity": "sha512-MCAxHL3Hz/+eU4LZk0ZbLWAIUueH/jHpSbrloxZ3Dil2RL3w6NSJd5gE8zS7gs1B/eMcE600Brf5xSDR8kA5HA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/fetch-http-handler": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4308,13 +4053,11 @@ }, "node_modules/@aws-sdk/util-stream-browser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-stream-node": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-stream-node/-/util-stream-node-3.257.0.tgz", - "integrity": "sha512-UlLEerQCNejNulYmGXm/4X463n8n21foA2d6kgJ4AUSMWWhoRBjfwrM4gI7tA30zh9U81d6xbUtoOQTqKVtMTw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/node-http-handler": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4327,13 +4070,11 @@ }, "node_modules/@aws-sdk/util-stream-node/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-uri-escape": { "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz", - "integrity": "sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4343,13 +4084,11 @@ }, "node_modules/@aws-sdk/util-uri-escape/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-user-agent-browser": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.257.0.tgz", - "integrity": "sha512-YdavWK6/8Cw6mypEgysGGX/dT9p9qnzFbnN5PQsUY+JJk2Nx8fKFydjGiQ+6rWPeW17RAv9mmbboh9uPVWxVlw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.257.0", "bowser": "^2.11.0", @@ -4358,13 +4097,11 @@ }, "node_modules/@aws-sdk/util-user-agent-browser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-user-agent-node": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.259.0.tgz", - "integrity": "sha512-R0VTmNs+ySDDebU98BUbsLyeIM5YmAEr9esPpy15XfSy3AWmAeru8nLlztdaLilHZzLIDzvM2t7NGk/FzZFCvA==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/node-config-provider": "3.259.0", "@aws-sdk/types": "3.257.0", @@ -4384,13 +4121,11 @@ }, "node_modules/@aws-sdk/util-user-agent-node/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-utf8": { "version": "3.254.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.254.0.tgz", - "integrity": "sha512-14Kso/eIt5/qfIBmhEL9L1IfyUqswjSTqO2mY7KOzUZ9SZbwn3rpxmtkhmATkRjD7XIlLKaxBkI7tU9Zjzj8Kw==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/util-buffer-from": "3.208.0", "tslib": "^2.3.1" @@ -4401,26 +4136,22 @@ }, "node_modules/@aws-sdk/util-utf8-browser": { "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" } }, "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-utf8/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/util-waiter": { "version": "3.257.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.257.0.tgz", - "integrity": "sha512-Fr6of3EDOcXVDs5534o7VsJMXdybB0uLy2LzeFAVSwGOY3geKhIquBAiUDqCVu9B+iTldrC0rQ9NIM7ZSpPG8w==", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/abort-controller": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4432,13 +4163,11 @@ }, "node_modules/@aws-sdk/util-waiter/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@aws-sdk/xml-builder": { "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.201.0.tgz", - "integrity": "sha512-brRdB1wwMgjWEnOQsv7zSUhIQuh7DEicrfslAqHop4S4FtSI3GQAShpQqgOpMTNFYcpaWKmE/Y1MJmNY7xLCnw==", + "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" }, @@ -4448,8 +4177,7 @@ }, "node_modules/@aws-sdk/xml-builder/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "node_modules/@babel/code-frame": { "version": "7.24.2", @@ -4750,8 +4478,7 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -5301,8 +5028,7 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -6360,8 +6086,7 @@ }, "node_modules/@dotcom-reliability-kit/app-info": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/app-info/-/app-info-2.1.0.tgz", - "integrity": "sha512-u7QicgkUbN58IMywvXmNuXxMK5bHUKfjeDC6s3u7TQg5uTGNicdrpBb8zB2O5K++g5KIlVnAafPcJct3ct9Nfw==", + "license": "MIT", "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x" @@ -6369,8 +6094,7 @@ }, "node_modules/@dotcom-reliability-kit/crash-handler": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/crash-handler/-/crash-handler-3.0.2.tgz", - "integrity": "sha512-+o8gfHC4B4RkqEThoiPU29qVeSlmJQ96sr6KDtoSVXg/J03QRK0mnYgvNsY0AonxyIdgZPD9Tteq6tDomTNP1A==", + "license": "MIT", "dependencies": { "@dotcom-reliability-kit/log-error": "^3.1.0" }, @@ -6381,9 +6105,8 @@ }, "node_modules/@dotcom-reliability-kit/eslint-config": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/eslint-config/-/eslint-config-2.0.0.tgz", - "integrity": "sha512-h9v1nZ4FRe2iHVm53QGoq4BafbQOWhtb0b/Kuxd3ed+HMvYn/ft8A/Av/Xg8vAnJ7uoJspWgkt8qxgDnwX5vxg==", "dev": true, + "license": "MIT", "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x" @@ -6394,8 +6117,7 @@ }, "node_modules/@dotcom-reliability-kit/log-error": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/log-error/-/log-error-3.1.0.tgz", - "integrity": "sha512-1HAjOQuNXZQkyIQ3A+i0SFUylFMKF+R4sx923RN2NU9DA+f3S4F7Yd+L7ty36ocZJL1YYrUjtcr2Yx9IC+hh7g==", + "license": "MIT", "dependencies": { "@dotcom-reliability-kit/app-info": "^2.1.0", "@dotcom-reliability-kit/logger": "^2.2.9", @@ -6409,8 +6131,7 @@ }, "node_modules/@dotcom-reliability-kit/logger": { "version": "2.2.9", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/logger/-/logger-2.2.9.tgz", - "integrity": "sha512-+3KSEdsypnz54VMgSVXnjyXTeJ5ZfyHF4jU3tcNcDrouGHT+JpD1ERkypfRfidwRRGtGup4FC2kjczpPGmecsw==", + "license": "MIT", "dependencies": { "@dotcom-reliability-kit/app-info": "^2.1.0", "@dotcom-reliability-kit/serialize-error": "^2.1.0", @@ -6427,8 +6148,7 @@ }, "node_modules/@dotcom-reliability-kit/serialize-error": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/serialize-error/-/serialize-error-2.1.0.tgz", - "integrity": "sha512-JYgnyvds/FZ0KJVRtOAsk9skue5i/vDBkRvQQg5Q/xlbwLdeUSAtD3XXBtlaohHov8kY7/I9UaXcoG6zXZ3a5Q==", + "license": "MIT", "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x" @@ -6436,8 +6156,7 @@ }, "node_modules/@dotcom-reliability-kit/serialize-request": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/serialize-request/-/serialize-request-2.2.0.tgz", - "integrity": "sha512-jM8GWWFzBFAXVkv1PPssAFC7mZLoEac9LV5HIINKmhxxe+av3eXJH53MwNQUARMqrIA3Hm7D7khT4L5gnuGcDg==", + "license": "MIT", "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x" @@ -6619,11 +6338,25 @@ "resolved": "plugins/webpack", "link": true }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -6636,9 +6369,8 @@ }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -6648,18 +6380,16 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", - "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -6680,19 +6410,17 @@ }, "node_modules/@eslint/js": { "version": "8.37.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", - "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@financial-times/eslint-config-next": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@financial-times/eslint-config-next/-/eslint-config-next-6.0.0.tgz", - "integrity": "sha512-8zQ4c4I11CTahJx4MI/WWT/xKSqubRAlHm37IyrqrO9KSA9+KB6iyMj5vF8WttxNB1M8sIWHTgqZwoJmgnHhxQ==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "eslint": ">=5.0.0", "eslint-plugin-no-only-tests": ">=2.0.0" @@ -6702,20 +6430,6 @@ "npm": "7.x || 8.x" } }, - "node_modules/@financial-times/n-fetch": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@financial-times/n-fetch/-/n-fetch-1.0.0.tgz", - "integrity": "sha512-6ayYnrlSJZvGU8/ZJEskxYH2kdvwJU/aL9MSXc3FmPj3dft7ecMxsB4p8PsWeJamHyd8EjaL7Mwm63LR2DwePg==", - "dependencies": { - "@dotcom-reliability-kit/logger": "^2.2.7", - "http-errors": "^1.6.1", - "node-fetch": "^2.0.0" - }, - "engines": { - "node": "16.x || 18.x", - "npm": "7.x || 8.x || 9.x" - } - }, "node_modules/@financial-times/package-json": { "version": "3.0.0", "license": "MIT" @@ -6726,9 +6440,8 @@ }, "node_modules/@google-automations/git-file-utils": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@google-automations/git-file-utils/-/git-file-utils-1.2.3.tgz", - "integrity": "sha512-CdxeRDIExWMdMIhRNbbqI3amtF72jct3XVEKquqinkSbUbzYx+ZxvakCwJB0FDS8xmq9mjEWEt0Cxy/+49A8kw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@octokit/rest": "19.0.5", "@octokit/types": "^8.0.0", @@ -6740,33 +6453,29 @@ }, "node_modules/@google-automations/git-file-utils/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@google-automations/git-file-utils/node_modules/@octokit/types": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } }, "node_modules/@google-automations/git-file-utils/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@google-automations/git-file-utils/node_modules/minimatch": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", - "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -6776,8 +6485,7 @@ }, "node_modules/@hapi/accept": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-6.0.0.tgz", - "integrity": "sha512-aG/Ml4kSBWCVmWvR8N8ULRuB385D8K/3OI7lquZQruH11eM7sHR5Nha30BbDzijJHtyV7Vwc6MlMwNfwb70ISg==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6786,8 +6494,7 @@ }, "node_modules/@hapi/ammo": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/ammo/-/ammo-6.0.0.tgz", - "integrity": "sha512-lhX7SYtWScQaeAIL5XnE54WzyDgS5RXVeEtFEovyZcTdVzTYbo0nem56Bwko1PBcRxRUIw1v2tMb6sjFs6vEwg==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0" @@ -6795,8 +6502,7 @@ }, "node_modules/@hapi/b64": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/b64/-/b64-6.0.0.tgz", - "integrity": "sha512-Es6o4BtzvMmNF28KJGuwUzUtMjF6ToZ1hQt3UOjaXc6TNkRefel+NyQSjc9b5q3Re7xwv23r0xK3Vo3yreaJHQ==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0" @@ -6804,8 +6510,7 @@ }, "node_modules/@hapi/boom": { "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-10.0.0.tgz", - "integrity": "sha512-1YVs9tLHhypBqqinKQRqh7FUERIolarQApO37OWkzD+z6y6USi871Sv746zBPKcIOBuI6g6y4FrwX87mmJ90Gg==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "10.x.x" @@ -6813,8 +6518,7 @@ }, "node_modules/@hapi/bounce": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bounce/-/bounce-3.0.0.tgz", - "integrity": "sha512-L0G4NcwwOYRhpcXeL76hNrLTUcObqtZMB3z4kcRVUZcR/w3v6C5Q1cTElV4/V7og1fG+wOyDR55UMFA+tWfhtA==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6823,14 +6527,12 @@ }, "node_modules/@hapi/bourne": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-3.0.0.tgz", - "integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==", + "license": "BSD-3-Clause", "peer": true }, "node_modules/@hapi/call": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@hapi/call/-/call-9.0.0.tgz", - "integrity": "sha512-Z6byqbEtKF3RIH2kWG6cX64RwEqHBWYEVkNoEx6oKvkPaTrC6WTPRgr+ANo9Xa8G1GXyvs/NCMTnn3Mdj12TSA==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6839,8 +6541,7 @@ }, "node_modules/@hapi/catbox": { "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@hapi/catbox/-/catbox-12.1.0.tgz", - "integrity": "sha512-60MCN5lgaXcuRTjMZqLR+DV0clS5RAFAwfYAQU2/na6PqrXHDRQcJwVMwP7jJayCrJm4POJlLDzZLuh1ba5XUg==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6851,8 +6552,7 @@ }, "node_modules/@hapi/catbox-memory": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/catbox-memory/-/catbox-memory-6.0.0.tgz", - "integrity": "sha512-A1O30g8GdaODx/GinytF6jFm772pdTPVWJe0cF2RiTOfhgIAAagzCcpBqRgQ8olLui0F5bzUF/SAi4BmkZ4yxA==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6861,8 +6561,7 @@ }, "node_modules/@hapi/content": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/content/-/content-6.0.0.tgz", - "integrity": "sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0" @@ -6870,8 +6569,7 @@ }, "node_modules/@hapi/cryptiles": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/cryptiles/-/cryptiles-6.0.0.tgz", - "integrity": "sha512-CUypQJI2F3HaKZjwlky3KyLu7p0O4WJXNJj+2AZ0czqwkwQIz8j+btOkzA3OMar8WTntnCrDx0f92PzxEK+JlA==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0" @@ -6882,14 +6580,12 @@ }, "node_modules/@hapi/file": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@hapi/file/-/file-3.0.0.tgz", - "integrity": "sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q==", + "license": "BSD-3-Clause", "peer": true }, "node_modules/@hapi/h2o2": { "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@hapi/h2o2/-/h2o2-10.0.0.tgz", - "integrity": "sha512-eY5uulCxtvN68xHCXt7dr7yQQrFgsQpCkBRsxbYjdkWCPl2PJBHktQGeXqrumz8XKR1RUmElqNZK2IjdUxK/gw==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6903,8 +6599,7 @@ }, "node_modules/@hapi/hapi": { "version": "21.2.1", - "resolved": "https://registry.npmjs.org/@hapi/hapi/-/hapi-21.2.1.tgz", - "integrity": "sha512-mDBhIi/zIYhWPaZF4Z8h7jUtWC3bz7xYuUyI5riXZV9DabFnNOKpQfOob6V5ZcDwEJfmnWHgJO37BVCn31BStQ==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/accept": "^6.0.0", @@ -6932,8 +6627,7 @@ }, "node_modules/@hapi/heavy": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@hapi/heavy/-/heavy-8.0.0.tgz", - "integrity": "sha512-NpKo74mF66GSwYu31IZwp11/6NmaUYxHeMTKSky09XBs8fVbzQDP83856+l+Ji6wxGmUeg75itCu1ujvEF6mdA==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6943,14 +6637,12 @@ }, "node_modules/@hapi/hoek": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-10.0.1.tgz", - "integrity": "sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw==", + "license": "BSD-3-Clause", "peer": true }, "node_modules/@hapi/iron": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@hapi/iron/-/iron-7.0.0.tgz", - "integrity": "sha512-NNXJP5fpeiTCPj/4OJG2PWBjWC0/V5D8YggS9RZeuBbfUUuTYE6TbdGqLUsCzIpPI54I8W5dhwEGbRv1CnWQtw==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/b64": "^6.0.0", @@ -6962,8 +6654,7 @@ }, "node_modules/@hapi/mimos": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@hapi/mimos/-/mimos-7.0.0.tgz", - "integrity": "sha512-ALORTrZrrBPOUX05rW4htNajoekEjQtUi1PB+17/3xs/hkdQ+gSEFbs5GdJihA49qWf7td3v4PgnvOe8mcf/jQ==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -6972,8 +6663,7 @@ }, "node_modules/@hapi/nigel": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hapi/nigel/-/nigel-5.0.0.tgz", - "integrity": "sha512-I9eq43BnSdz1BkvMpG7mFL7J+SIfn6DLNThuxFpIOAMUnkWbPgtcFP+HHrBAeoFkowfgQrr02vsIAkAPml4hvw==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -6985,8 +6675,7 @@ }, "node_modules/@hapi/pez": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/pez/-/pez-6.0.0.tgz", - "integrity": "sha512-3bMmsvlqrVNqaNEe4JWLZVpJ40jXuQ3vDy1+fbhyJmuAdMCMCkWexsKc7fT+mu18pFIwJzlenjc4/VE3weTq7w==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/b64": "^6.0.0", @@ -6998,8 +6687,7 @@ }, "node_modules/@hapi/podium": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hapi/podium/-/podium-5.0.0.tgz", - "integrity": "sha512-SbhFdu8LOIscMS82Zsoj9abcllAqbK4qBgznzJ9yr+vS2j1EomJTukkhxb76Lml0BHCd4Hn79F+3EQg06kcf8g==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -7009,8 +6697,7 @@ }, "node_modules/@hapi/shot": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-6.0.0.tgz", - "integrity": "sha512-RLGgzXy9GciJDunhY40NbVnLgYqp5gfBooZ2fOkAr4KbCEav/SJtYQS1N+knR7WFGzy8aooCR3XBUPI4ghHAkQ==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -7019,8 +6706,7 @@ }, "node_modules/@hapi/somever": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@hapi/somever/-/somever-4.1.0.tgz", - "integrity": "sha512-koNBYu7Jdcb7gaC4VcnU78rFxSlsYwuElm6NMznE0EEeznzJtvLLmDZX0SPX8kXWC/E7ONlE29HF/yiSOgWG1Q==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/bounce": "^3.0.0", @@ -7029,14 +6715,12 @@ }, "node_modules/@hapi/somever/node_modules/@hapi/hoek": { "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause", "peer": true }, "node_modules/@hapi/statehood": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@hapi/statehood/-/statehood-8.0.0.tgz", - "integrity": "sha512-umQTPID7BwmqAv9Rx7yLtbTNzsYg4va96aLqKneb3mlBQG32uq4iOQZ6luwBVACDFhqU3C3ewhznhukN09ZkZQ==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -7050,8 +6734,7 @@ }, "node_modules/@hapi/subtext": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-8.0.0.tgz", - "integrity": "sha512-fD+LY1U1SIUNHZJrNMIbuGl3CAd9JN8slljarFO4b8RrifkzjqbvdlZu/6iT6zlNM35GtDExf7hIepbUFUkT7A==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -7065,8 +6748,7 @@ }, "node_modules/@hapi/teamwork": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/teamwork/-/teamwork-6.0.0.tgz", - "integrity": "sha512-05HumSy3LWfXpmJ9cr6HzwhAavrHkJ1ZRCmNE2qJMihdM5YcWreWPfyN0yKT2ZjCM92au3ZkuodjBxOibxM67A==", + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">=14.0.0" @@ -7074,8 +6756,7 @@ }, "node_modules/@hapi/topo": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.0.tgz", - "integrity": "sha512-aorJvN1Q1n5xrZuA50Z4X6adI6VAM2NalIVm46ALL9LUvdoqhof3JPY69jdJH8asM3PsWr2SUVYzp57EqUP41A==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0" @@ -7083,8 +6764,7 @@ }, "node_modules/@hapi/validate": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/validate/-/validate-2.0.0.tgz", - "integrity": "sha512-w5m8MvBgqGndbMIB+AWmXTb8CLtF1DlIxbnbAHNAo7aFuNQuI1Ywc2e0zDLK5fbFXDoqRzNrHnC7JjNJ+hDigw==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -7093,8 +6773,7 @@ }, "node_modules/@hapi/vise": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-5.0.0.tgz", - "integrity": "sha512-bz/PA7DHIvsd/2eoW7t9WpU8+k9pofZHppYEn1mCTOVnC/cGN3hCEYaoAe6BpoeJM72iJDKZEOWvQvfgCrmzxA==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0" @@ -7102,8 +6781,7 @@ }, "node_modules/@hapi/wreck": { "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-18.0.0.tgz", - "integrity": "sha512-Yk9STxoM06Hjjq58cH0KFG91u9F2h9eVE72o8vUr3AfK80qt7I2POG5+cDGTEntbnvvzm0ERow2sjG3QsqCWUA==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -7113,9 +6791,8 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", @@ -7127,9 +6804,8 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -7321,9 +6997,9 @@ } }, "node_modules/@jest/console/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/@jest/core": { "version": "29.7.0", @@ -7531,9 +7207,9 @@ } }, "node_modules/@jest/core/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/@jest/core/node_modules/ts-node": { "version": "10.9.2", @@ -7773,9 +7449,9 @@ } }, "node_modules/@jest/expect/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/@jest/fake-timers": { "version": "27.5.1", @@ -7980,9 +7656,9 @@ } }, "node_modules/@jest/reporters/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/@jest/reporters/node_modules/semver": { "version": "7.6.0", @@ -8159,8 +7835,7 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -8175,8 +7850,7 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -8189,16 +7863,14 @@ }, "node_modules/@kwsites/file-exists": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "license": "MIT", "dependencies": { "debug": "^4.1.1" } }, "node_modules/@kwsites/promise-deferred": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" + "license": "MIT" }, "node_modules/@lerna/child-process": { "version": "4.0.0", @@ -8764,14 +8436,12 @@ }, "node_modules/@npm/types": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@npm/types/-/types-1.0.2.tgz", - "integrity": "sha512-KXZccTDEnWqNrrx6JjpJKU/wJvNeg9BDgjS0XhmlZab7br921HtyVbsYzJr4L+xIvjdJ20Wh9dgxgCI2a5CEQw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@npmcli/fs": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -8841,9 +8511,7 @@ }, "node_modules/@npmcli/move-file": { "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==", - "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -8854,21 +8522,18 @@ }, "node_modules/@npmcli/node-gyp": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz", - "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==" + "license": "ISC" }, "node_modules/@npmcli/promise-spawn": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", - "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "license": "ISC", "dependencies": { "infer-owner": "^1.0.4" } }, "node_modules/@npmcli/run-script": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-2.0.0.tgz", - "integrity": "sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig==", + "license": "ISC", "dependencies": { "@npmcli/node-gyp": "^1.0.2", "@npmcli/promise-spawn": "^1.3.2", @@ -8878,8 +8543,7 @@ }, "node_modules/@octokit/auth-token": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz", - "integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==", + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0" }, @@ -8889,21 +8553,18 @@ }, "node_modules/@octokit/auth-token/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" + "license": "MIT" }, "node_modules/@octokit/auth-token/node_modules/@octokit/types": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } }, "node_modules/@octokit/core": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz", - "integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==", + "license": "MIT", "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", @@ -8919,8 +8580,7 @@ }, "node_modules/@octokit/core/node_modules/@octokit/endpoint": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", - "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "is-plain-object": "^5.0.0", @@ -8932,13 +8592,11 @@ }, "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" + "license": "MIT" }, "node_modules/@octokit/core/node_modules/@octokit/request": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", + "license": "MIT", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -8953,8 +8611,7 @@ }, "node_modules/@octokit/core/node_modules/@octokit/request-error": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", - "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "deprecation": "^2.0.0", @@ -8966,8 +8623,7 @@ }, "node_modules/@octokit/core/node_modules/@octokit/types": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } @@ -8983,8 +8639,7 @@ }, "node_modules/@octokit/graphql": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz", - "integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==", + "license": "MIT", "dependencies": { "@octokit/request": "^6.0.0", "@octokit/types": "^8.0.0", @@ -8996,8 +8651,7 @@ }, "node_modules/@octokit/graphql/node_modules/@octokit/endpoint": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", - "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "is-plain-object": "^5.0.0", @@ -9009,13 +8663,11 @@ }, "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" + "license": "MIT" }, "node_modules/@octokit/graphql/node_modules/@octokit/request": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", + "license": "MIT", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -9030,8 +8682,7 @@ }, "node_modules/@octokit/graphql/node_modules/@octokit/request-error": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", - "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "deprecation": "^2.0.0", @@ -9043,8 +8694,7 @@ }, "node_modules/@octokit/graphql/node_modules/@octokit/types": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } @@ -9055,8 +8705,7 @@ }, "node_modules/@octokit/plugin-paginate-rest": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", - "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0" }, @@ -9069,29 +8718,25 @@ }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" + "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } }, "node_modules/@octokit/plugin-request-log": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "license": "MIT", "peerDependencies": { "@octokit/core": ">=3" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz", - "integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==", + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "deprecation": "^2.3.1" @@ -9105,13 +8750,11 @@ }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" + "license": "MIT" }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } @@ -9139,8 +8782,7 @@ }, "node_modules/@octokit/rest": { "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz", - "integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==", + "license": "MIT", "dependencies": { "@octokit/core": "^4.1.0", "@octokit/plugin-paginate-rest": "^5.0.0", @@ -9166,8 +8808,7 @@ }, "node_modules/@serverless/dashboard-plugin": { "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@serverless/dashboard-plugin/-/dashboard-plugin-6.2.3.tgz", - "integrity": "sha512-iTZhpZbiVl6G2AyfgoqxemqqpG4pUceWys3GsyZtjimnfnGd2UFBOMVUMTavLhYia7lQc4kQVuXQ+afLlkg+pQ==", + "license": "MIT", "peer": true, "dependencies": { "@serverless/event-mocks": "^1.1.1", @@ -9197,8 +8838,7 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/fs-extra": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", "peer": true, "dependencies": { "at-least-node": "^1.0.0", @@ -9212,8 +8852,7 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/is-wsl": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", "peer": true, "dependencies": { "is-docker": "^2.0.0" @@ -9224,8 +8863,7 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "peer": true, "dependencies": { "yallist": "^4.0.0" @@ -9236,8 +8874,7 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/node-fetch": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "license": "MIT", "peer": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -9256,8 +8893,7 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/open": { "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", "peer": true, "dependencies": { "is-docker": "^2.0.0", @@ -9272,8 +8908,7 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/semver": { "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "license": "ISC", "peer": true, "dependencies": { "lru-cache": "^6.0.0" @@ -9287,14 +8922,12 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", "peer": true }, "node_modules/@serverless/dashboard-plugin/node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "peer": true, "bin": { "uuid": "dist/bin/uuid" @@ -9302,14 +8935,12 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", "peer": true }, "node_modules/@serverless/dashboard-plugin/node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "peer": true, "dependencies": { "tr46": "~0.0.3", @@ -9318,14 +8949,12 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "peer": true }, "node_modules/@serverless/event-mocks": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@serverless/event-mocks/-/event-mocks-1.1.1.tgz", - "integrity": "sha512-YAV5V/y+XIOfd+HEVeXfPWZb8C6QLruFk9tBivoX2roQLWVq145s4uxf8D0QioCueuRzkukHUS4JIj+KVoS34A==", + "license": "Apache-2.0", "peer": true, "dependencies": { "@types/lodash": "^4.14.123", @@ -9334,8 +8963,7 @@ }, "node_modules/@serverless/platform-client": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@serverless/platform-client/-/platform-client-4.3.2.tgz", - "integrity": "sha512-DAa5Z0JAZc6UfrTZLYwqoZxgAponZpFwaqd7WzzMA+loMCkYWyJNwxrAmV6cr2UUJpkko4toPZuJ3vM9Ie+NDA==", + "license": "ISC", "peer": true, "dependencies": { "adm-zip": "^0.5.5", @@ -9360,8 +8988,7 @@ }, "node_modules/@serverless/platform-client/node_modules/archiver": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", - "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -9378,8 +9005,7 @@ }, "node_modules/@serverless/platform-client/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", "peer": true, "dependencies": { "sprintf-js": "~1.0.2" @@ -9387,8 +9013,7 @@ }, "node_modules/@serverless/platform-client/node_modules/compress-commons": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", - "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "license": "MIT", "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", @@ -9402,8 +9027,7 @@ }, "node_modules/@serverless/platform-client/node_modules/crc32-stream": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", - "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "license": "MIT", "peer": true, "dependencies": { "crc-32": "^1.2.0", @@ -9415,8 +9039,7 @@ }, "node_modules/@serverless/platform-client/node_modules/js-yaml": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -9428,9 +9051,7 @@ }, "node_modules/@serverless/platform-client/node_modules/querystring": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", - "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "license": "MIT", "peer": true, "engines": { "node": ">=0.4.x" @@ -9438,14 +9059,12 @@ }, "node_modules/@serverless/platform-client/node_modules/throat": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", - "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "license": "MIT", "peer": true }, "node_modules/@serverless/platform-client/node_modules/zip-stream": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", - "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -9458,8 +9077,7 @@ }, "node_modules/@serverless/utils": { "version": "6.8.2", - "resolved": "https://registry.npmjs.org/@serverless/utils/-/utils-6.8.2.tgz", - "integrity": "sha512-FW8zdG8OPoF6qgyutiMhz4m/5SxbQjoQdbaGcW3wU6xe3QzQh41Hif7I3Xuu4J62CvxiWuz19sxNDJz2mTcskw==", + "license": "MIT", "peer": true, "dependencies": { "archive-type": "^4.0.0", @@ -9501,8 +9119,7 @@ }, "node_modules/@serverless/utils/node_modules/@sindresorhus/is": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -9513,8 +9130,7 @@ }, "node_modules/@serverless/utils/node_modules/@szmarczak/http-timer": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", "peer": true, "dependencies": { "defer-to-connect": "^2.0.0" @@ -9525,8 +9141,7 @@ }, "node_modules/@serverless/utils/node_modules/cacheable-request": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "license": "MIT", "peer": true, "dependencies": { "clone-response": "^1.0.2", @@ -9543,8 +9158,7 @@ }, "node_modules/@serverless/utils/node_modules/cacheable-request/node_modules/get-stream": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", "peer": true, "dependencies": { "pump": "^3.0.0" @@ -9558,14 +9172,13 @@ }, "node_modules/@serverless/utils/node_modules/ci-info": { "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -9573,8 +9186,7 @@ }, "node_modules/@serverless/utils/node_modules/decompress-response": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", "peer": true, "dependencies": { "mimic-response": "^3.1.0" @@ -9588,8 +9200,7 @@ }, "node_modules/@serverless/utils/node_modules/defer-to-connect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -9597,8 +9208,7 @@ }, "node_modules/@serverless/utils/node_modules/got": { "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", "peer": true, "dependencies": { "@sindresorhus/is": "^4.0.0", @@ -9622,8 +9232,7 @@ }, "node_modules/@serverless/utils/node_modules/inquirer": { "version": "8.2.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", - "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "license": "MIT", "peer": true, "dependencies": { "ansi-escapes": "^4.2.1", @@ -9648,20 +9257,17 @@ }, "node_modules/@serverless/utils/node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT", "peer": true }, "node_modules/@serverless/utils/node_modules/jwt-decode": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==", + "license": "MIT", "peer": true }, "node_modules/@serverless/utils/node_modules/keyv": { "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "license": "MIT", "peer": true, "dependencies": { "json-buffer": "3.0.1" @@ -9669,8 +9275,7 @@ }, "node_modules/@serverless/utils/node_modules/lowercase-keys": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -9678,8 +9283,7 @@ }, "node_modules/@serverless/utils/node_modules/mimic-response": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -9690,8 +9294,7 @@ }, "node_modules/@serverless/utils/node_modules/normalize-url": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -9702,8 +9305,7 @@ }, "node_modules/@serverless/utils/node_modules/p-cancelable": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -9711,8 +9313,7 @@ }, "node_modules/@serverless/utils/node_modules/responselike": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", "peer": true, "dependencies": { "lowercase-keys": "^2.0.0" @@ -9723,8 +9324,7 @@ }, "node_modules/@serverless/utils/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -9738,8 +9338,7 @@ }, "node_modules/@serverless/utils/node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "peer": true, "bin": { "uuid": "dist/bin/uuid" @@ -9747,8 +9346,7 @@ }, "node_modules/@serverless/utils/node_modules/write-file-atomic": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "license": "ISC", "peer": true, "dependencies": { "imurmurhash": "^0.1.4", @@ -9800,8 +9398,7 @@ }, "node_modules/@tokenizer/token": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT", "peer": true }, "node_modules/@tootallnate/once": { @@ -9828,9 +9425,8 @@ }, "node_modules/@tsconfig/node16": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "devOptional": true + "devOptional": true, + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -9870,8 +9466,7 @@ }, "node_modules/@types/cacheable-request": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", "peer": true, "dependencies": { "@types/http-cache-semantics": "*", @@ -9924,8 +9519,7 @@ }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "license": "MIT", "peer": true }, "node_modules/@types/istanbul-lib-coverage": { @@ -9972,8 +9566,7 @@ }, "node_modules/@types/keyv": { "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", "peer": true, "dependencies": { "@types/node": "*" @@ -9981,8 +9574,7 @@ }, "node_modules/@types/lodash": { "version": "4.14.189", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.189.tgz", - "integrity": "sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==" + "license": "MIT" }, "node_modules/@types/mime": { "version": "2.0.3", @@ -10006,14 +9598,12 @@ }, "node_modules/@types/node": { "version": "16.18.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.23.tgz", - "integrity": "sha512-XAMpaw1s1+6zM+jn2tmw8MyaRDIJfXxqmIQIS0HfoGYPuf7dUWeiUKopwq13KFX9lEp1+THGtlaaYx39Nxr58g==" + "license": "MIT" }, "node_modules/@types/node-fetch": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "form-data": "^3.0.0" @@ -10125,8 +9715,7 @@ }, "node_modules/@types/responselike": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "license": "MIT", "peer": true, "dependencies": { "@types/node": "*" @@ -10138,9 +9727,8 @@ }, "node_modules/@types/semver": { "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ssri": { "version": "7.1.1", @@ -10164,9 +9752,8 @@ }, "node_modules/@types/temp": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@types/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-+VfWIwrlept2VBTj7Y2wQnI/Xfscy1u8Pyj/puYwss6V1IblXn1x7S0S9eFh6KyBolgLCm+rUFzhFAbdkR691g==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -10198,8 +9785,7 @@ }, "node_modules/@types/yauzl": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "license": "MIT", "optional": true, "dependencies": { "@types/node": "*" @@ -10207,9 +9793,8 @@ }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.0.tgz", - "integrity": "sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.57.0", @@ -10241,9 +9826,8 @@ }, "node_modules/@typescript-eslint/parser": { "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.0.tgz", - "integrity": "sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "5.57.0", "@typescript-eslint/types": "5.57.0", @@ -10268,9 +9852,8 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz", - "integrity": "sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.57.0", "@typescript-eslint/visitor-keys": "5.57.0" @@ -10285,9 +9868,8 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.0.tgz", - "integrity": "sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "5.57.0", "@typescript-eslint/utils": "5.57.0", @@ -10312,9 +9894,8 @@ }, "node_modules/@typescript-eslint/types": { "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.0.tgz", - "integrity": "sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -10325,9 +9906,8 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz", - "integrity": "sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "5.57.0", "@typescript-eslint/visitor-keys": "5.57.0", @@ -10352,9 +9932,8 @@ }, "node_modules/@typescript-eslint/utils": { "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.0.tgz", - "integrity": "sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -10378,9 +9957,8 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.57.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz", - "integrity": "sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.57.0", "eslint-visitor-keys": "^3.3.0" @@ -10395,9 +9973,8 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -10645,9 +10222,8 @@ }, "node_modules/@xmldom/xmldom": { "version": "0.8.6", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz", - "integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -10662,8 +10238,7 @@ }, "node_modules/2-thenable": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/2-thenable/-/2-thenable-1.0.0.tgz", - "integrity": "sha512-HqiDzaLDFCXkcCO/SwoyhRwqYtINFHF7t9BDRq4x90TOKNAJpiqUt9X5lQ08bwxYzc067HUywDjGySpebHcUpw==", + "license": "ISC", "peer": true, "dependencies": { "d": "1", @@ -10676,8 +10251,7 @@ }, "node_modules/abort-controller": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -10716,8 +10290,7 @@ }, "node_modules/adm-zip": { "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=6.0" @@ -10779,8 +10352,7 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", "peer": true, "dependencies": { "ajv": "^8.0.0" @@ -10796,8 +10368,7 @@ }, "node_modules/ajv-formats/node_modules/ajv": { "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "license": "MIT", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -10812,8 +10383,7 @@ }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT", "peer": true }, "node_modules/ajv-keywords": { @@ -10872,8 +10442,7 @@ }, "node_modules/any-promise": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.2", @@ -10892,8 +10461,7 @@ }, "node_modules/archive-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", - "integrity": "sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==", + "license": "MIT", "peer": true, "dependencies": { "file-type": "^4.2.0" @@ -10904,8 +10472,7 @@ }, "node_modules/archive-type/node_modules/file-type": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", - "integrity": "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -11016,8 +10583,7 @@ }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -11036,9 +10602,8 @@ }, "node_modules/array-includes": { "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -11055,8 +10620,7 @@ }, "node_modules/array-unflat-js": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/array-unflat-js/-/array-unflat-js-0.1.3.tgz", - "integrity": "sha512-8pljkLj4vfz2i7Tf3yB31tRrszjP8/kwIyABGfcZ1GcHlvdUB0Sbx0WzQkOPMqUBxa/bu4+/NAyHEpDtZJzlJw==", + "license": "MIT", "peer": true, "engines": { "node": ">=14.18.0" @@ -11071,8 +10635,7 @@ }, "node_modules/array-uniq": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11086,9 +10649,8 @@ }, "node_modules/array.prototype.flat": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -11104,9 +10666,8 @@ }, "node_modules/array.prototype.flatmap": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -11122,8 +10683,7 @@ }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -11151,8 +10711,7 @@ }, "node_modules/asap": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT", "peer": true }, "node_modules/asn1": { @@ -11235,16 +10794,14 @@ }, "node_modules/async-retry": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "license": "MIT", "dependencies": { "retry": "0.13.1" } }, "node_modules/async-retry/node_modules/retry": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", "engines": { "node": ">= 4" } @@ -11255,8 +10812,7 @@ }, "node_modules/at-least-node": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", "peer": true, "engines": { "node": ">= 4.0.0" @@ -11274,16 +10830,14 @@ }, "node_modules/atomic-sleep": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", "engines": { "node": ">=8.0.0" } }, "node_modules/available-typed-arrays": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -11296,8 +10850,7 @@ }, "node_modules/aws-sdk": { "version": "2.1308.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1308.0.tgz", - "integrity": "sha512-tm4UXah8dCqt1geyxrtoyp6dN5QhuLjNeACUZEsffww5oZPMx24EX9dAtvtSu3UfIHwmbR74QomYi1c1u8Jndg==", + "license": "Apache-2.0", "peer": true, "dependencies": { "buffer": "4.9.2", @@ -11317,8 +10870,7 @@ }, "node_modules/aws-sdk/node_modules/events": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.4.x" @@ -11326,20 +10878,17 @@ }, "node_modules/aws-sdk/node_modules/ieee754": { "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "license": "BSD-3-Clause", "peer": true }, "node_modules/aws-sdk/node_modules/punycode": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "license": "MIT", "peer": true }, "node_modules/aws-sdk/node_modules/url": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "license": "MIT", "peer": true, "dependencies": { "punycode": "1.3.2", @@ -11348,8 +10897,7 @@ }, "node_modules/aws-sdk/node_modules/util": { "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", "peer": true, "dependencies": { "inherits": "^2.0.3", @@ -11361,8 +10909,7 @@ }, "node_modules/aws-sdk/node_modules/uuid": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", - "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "license": "MIT", "peer": true, "bin": { "uuid": "dist/bin/uuid" @@ -11381,16 +10928,14 @@ }, "node_modules/axe-core": { "version": "4.4.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.2.tgz", - "integrity": "sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA==", + "license": "MPL-2.0", "engines": { "node": ">=12" } }, "node_modules/axios": { "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "license": "MIT", "peer": true, "dependencies": { "follow-redirects": "^1.14.0" @@ -11621,13 +11166,11 @@ }, "node_modules/before-after-hook": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + "license": "Apache-2.0" }, "node_modules/bfj": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", - "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", + "license": "MIT", "dependencies": { "bluebird": "^3.5.5", "check-types": "^11.1.1", @@ -11705,13 +11248,11 @@ }, "node_modules/bowser": { "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + "license": "MIT" }, "node_modules/boxen": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "license": "MIT", "peer": true, "dependencies": { "ansi-align": "^3.0.0", @@ -11907,8 +11448,7 @@ }, "node_modules/buffer-alloc": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "license": "MIT", "peer": true, "dependencies": { "buffer-alloc-unsafe": "^1.1.0", @@ -11917,8 +11457,7 @@ }, "node_modules/buffer-alloc-unsafe": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "license": "MIT", "peer": true }, "node_modules/buffer-crc32": { @@ -11930,8 +11469,7 @@ }, "node_modules/buffer-fill": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "license": "MIT", "peer": true }, "node_modules/buffer-from": { @@ -11944,8 +11482,7 @@ }, "node_modules/builtin-modules": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -11962,10 +11499,23 @@ "version": "1.0.3", "license": "MIT" }, + "node_modules/bundle-require": { + "version": "4.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.17" + } + }, "node_modules/cacache": { "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -11992,8 +11542,7 @@ }, "node_modules/cacache/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -12003,8 +11552,7 @@ }, "node_modules/cacache/node_modules/tar": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -12019,16 +11567,14 @@ }, "node_modules/cacache/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", "engines": { "node": ">=8" } }, "node_modules/cacache/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/cache-base": { "version": "1.0.1", @@ -12050,8 +11596,7 @@ }, "node_modules/cacheable-lookup": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", "peer": true, "engines": { "node": ">=10.6.0" @@ -12098,8 +11643,7 @@ }, "node_modules/cachedir": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -12107,8 +11651,7 @@ }, "node_modules/call-bind": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -12209,7 +11752,8 @@ }, "node_modules/char-regex": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "engines": { "node": ">=10" } @@ -12240,13 +11784,11 @@ }, "node_modules/check-types": { "version": "11.1.2", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz", - "integrity": "sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ==" + "license": "MIT" }, "node_modules/cheerio": { "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "license": "MIT", "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", @@ -12265,8 +11807,7 @@ }, "node_modules/cheerio-select": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", @@ -12281,8 +11822,7 @@ }, "node_modules/cheerio/node_modules/parse5": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", - "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "license": "MIT", "dependencies": { "entities": "^4.3.0" }, @@ -12292,8 +11832,7 @@ }, "node_modules/child-process-ext": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/child-process-ext/-/child-process-ext-2.1.1.tgz", - "integrity": "sha512-0UQ55f51JBkOFa+fvR76ywRzxiPwQS3Xe8oe5bZRphpv+dIMeerW5Zn5e4cUy4COJwVtJyU0R79RMnw+aCqmGA==", + "license": "ISC", "peer": true, "dependencies": { "cross-spawn": "^6.0.5", @@ -12305,8 +11844,7 @@ }, "node_modules/child-process-ext/node_modules/cross-spawn": { "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "license": "MIT", "peer": true, "dependencies": { "nice-try": "^1.0.4", @@ -12321,8 +11859,7 @@ }, "node_modules/child-process-ext/node_modules/path-key": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -12330,8 +11867,7 @@ }, "node_modules/child-process-ext/node_modules/semver": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "license": "ISC", "peer": true, "bin": { "semver": "bin/semver" @@ -12389,8 +11925,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "license": "MIT" + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" }, "node_modules/class-utils": { "version": "0.3.6", @@ -12424,8 +11961,7 @@ }, "node_modules/cli-color": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", - "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", + "license": "ISC", "peer": true, "dependencies": { "d": "^1.0.1", @@ -12450,8 +11986,7 @@ }, "node_modules/cli-highlight": { "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "license": "ISC", "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", @@ -12470,26 +12005,22 @@ }, "node_modules/cli-highlight/node_modules/parse5": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + "license": "MIT" }, "node_modules/cli-highlight/node_modules/parse5-htmlparser2-tree-adapter": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "license": "MIT", "dependencies": { "parse5": "^6.0.1" } }, "node_modules/cli-highlight/node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "license": "MIT" }, "node_modules/cli-highlight/node_modules/yargs": { "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -12505,8 +12036,7 @@ }, "node_modules/cli-progress-footer": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/cli-progress-footer/-/cli-progress-footer-2.3.2.tgz", - "integrity": "sha512-uzHGgkKdeA9Kr57eyH1W5HGiNShP8fV1ETq04HDNM1Un6ShXbHhwi/H8LNV9L1fQXKjEw0q5FUkEVNuZ+yZdSw==", + "license": "ISC", "peer": true, "dependencies": { "cli-color": "^2.0.2", @@ -12533,8 +12063,7 @@ }, "node_modules/cli-sprintf-format": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cli-sprintf-format/-/cli-sprintf-format-1.1.1.tgz", - "integrity": "sha512-BbEjY9BEdA6wagVwTqPvmAwGB24U93rQPBFZUT8lNCDxXzre5LFHQUTJc70czjgUomVg8u8R5kW8oY9DYRFNeg==", + "license": "ISC", "peer": true, "dependencies": { "cli-color": "^2.0.1", @@ -12548,8 +12077,7 @@ }, "node_modules/cli-sprintf-format/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -12557,8 +12085,7 @@ }, "node_modules/cli-sprintf-format/node_modules/supports-color": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "license": "MIT", "peer": true, "dependencies": { "has-flag": "^3.0.0" @@ -12599,8 +12126,7 @@ }, "node_modules/clone": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.8" @@ -12638,7 +12164,8 @@ }, "node_modules/co": { "version": "4.6.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -12654,9 +12181,8 @@ }, "node_modules/code-suggester": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/code-suggester/-/code-suggester-4.1.1.tgz", - "integrity": "sha512-AGO1o4Bl4JlSeVCiFL9IpfH0MJyhtaMAwbO7qM+t/cNSz6URTPUZN+0fTtnAWfyeO5GbcGC9e18ArDbjkgpruA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@octokit/rest": "^19.0.5", "@types/yargs": "^16.0.0", @@ -12675,9 +12201,8 @@ }, "node_modules/code-suggester/node_modules/yargs": { "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -12692,8 +12217,9 @@ } }, "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "license": "MIT" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" }, "node_modules/collection-visit": { "version": "1.0.0", @@ -12927,8 +12453,7 @@ }, "node_modules/content-disposition": { "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "peer": true, "dependencies": { "safe-buffer": "5.2.1" @@ -12939,8 +12464,6 @@ }, "node_modules/content-disposition/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -12955,6 +12478,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "peer": true }, "node_modules/conventional-changelog-angular": { @@ -13050,8 +12574,7 @@ }, "node_modules/cookiejar": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" + "license": "MIT" }, "node_modules/copy-concurrently": { "version": "1.0.5", @@ -13123,8 +12646,7 @@ }, "node_modules/cosmiconfig": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -13213,8 +12735,7 @@ }, "node_modules/crc-32": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", "peer": true, "bin": { "crc32": "bin/crc32.njs" @@ -13324,7 +12845,7 @@ "node": ">=12" } }, - "node_modules/create-jest/node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "node_modules/create-jest/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", @@ -13452,9 +12973,9 @@ } }, "node_modules/create-jest/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/create-jest/node_modules/ts-node": { "version": "10.9.2", @@ -13507,8 +13028,7 @@ }, "node_modules/cron-parser": { "version": "4.7.1", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.7.1.tgz", - "integrity": "sha512-WguFaoQ0hQ61SgsCZLHUcNbAvlK0lypKXu62ARguefYmjzaOXIVRNrAmyXzabTwUn4sQvQLkk6bjH+ipGfw8bA==", + "license": "MIT", "peer": true, "dependencies": { "luxon": "^3.2.1" @@ -13519,16 +13039,14 @@ }, "node_modules/cross-fetch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "license": "MIT", "dependencies": { "node-fetch": "2.6.7" } }, "node_modules/cross-fetch/node_modules/node-fetch": { "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -13546,18 +13064,15 @@ }, "node_modules/cross-fetch/node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "license": "MIT" }, "node_modules/cross-fetch/node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "license": "BSD-2-Clause" }, "node_modules/cross-fetch/node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -13603,8 +13118,7 @@ }, "node_modules/css-select": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", @@ -13648,8 +13162,7 @@ }, "node_modules/d": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "license": "ISC", "peer": true, "dependencies": { "es5-ext": "^0.10.50", @@ -13658,8 +13171,7 @@ }, "node_modules/d/node_modules/type": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "license": "ISC", "peer": true }, "node_modules/daemonize2": { @@ -13692,8 +13204,7 @@ }, "node_modules/data-view-buffer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -13708,8 +13219,7 @@ }, "node_modules/data-view-byte-length": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -13724,8 +13234,7 @@ }, "node_modules/data-view-byte-offset": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -13748,8 +13257,7 @@ }, "node_modules/dayjs": { "version": "1.11.7", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", - "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==", + "license": "MIT", "peer": true }, "node_modules/debug": { @@ -13797,16 +13305,14 @@ }, "node_modules/decode-uri-component": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", "engines": { "node": ">=0.10" } }, "node_modules/decompress": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", - "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "license": "MIT", "peer": true, "dependencies": { "decompress-tar": "^4.0.0", @@ -13835,8 +13341,7 @@ }, "node_modules/decompress-tar": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "license": "MIT", "peer": true, "dependencies": { "file-type": "^5.2.0", @@ -13849,8 +13354,7 @@ }, "node_modules/decompress-tar/node_modules/bl": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "license": "MIT", "peer": true, "dependencies": { "readable-stream": "^2.3.5", @@ -13859,8 +13363,7 @@ }, "node_modules/decompress-tar/node_modules/file-type": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -13868,8 +13371,7 @@ }, "node_modules/decompress-tar/node_modules/is-stream": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -13877,8 +13379,7 @@ }, "node_modules/decompress-tar/node_modules/readable-stream": { "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "license": "MIT", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -13892,8 +13393,7 @@ }, "node_modules/decompress-tar/node_modules/string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -13901,8 +13401,7 @@ }, "node_modules/decompress-tar/node_modules/tar-stream": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "license": "MIT", "peer": true, "dependencies": { "bl": "^1.0.0", @@ -13919,8 +13418,7 @@ }, "node_modules/decompress-tarbz2": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "license": "MIT", "peer": true, "dependencies": { "decompress-tar": "^4.1.0", @@ -13935,8 +13433,7 @@ }, "node_modules/decompress-tarbz2/node_modules/file-type": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -13944,8 +13441,7 @@ }, "node_modules/decompress-tarbz2/node_modules/is-stream": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -13953,8 +13449,7 @@ }, "node_modules/decompress-targz": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "license": "MIT", "peer": true, "dependencies": { "decompress-tar": "^4.1.1", @@ -13967,8 +13462,7 @@ }, "node_modules/decompress-targz/node_modules/file-type": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -13976,8 +13470,7 @@ }, "node_modules/decompress-targz/node_modules/is-stream": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -13985,8 +13478,7 @@ }, "node_modules/decompress-unzip": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", + "license": "MIT", "peer": true, "dependencies": { "file-type": "^3.8.0", @@ -14000,8 +13492,7 @@ }, "node_modules/decompress-unzip/node_modules/file-type": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -14009,8 +13500,7 @@ }, "node_modules/decompress-unzip/node_modules/get-stream": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", + "license": "MIT", "peer": true, "dependencies": { "object-assign": "^4.0.1", @@ -14022,8 +13512,7 @@ }, "node_modules/decompress-unzip/node_modules/pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -14031,8 +13520,7 @@ }, "node_modules/decompress/node_modules/make-dir": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "license": "MIT", "peer": true, "dependencies": { "pify": "^3.0.0" @@ -14043,8 +13531,7 @@ }, "node_modules/decompress/node_modules/make-dir/node_modules/pify": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -14052,8 +13539,7 @@ }, "node_modules/decompress/node_modules/pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -14095,8 +13581,7 @@ }, "node_modules/defaults": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", "peer": true, "dependencies": { "clone": "^1.0.2" @@ -14112,8 +13597,7 @@ }, "node_modules/deferred": { "version": "0.7.11", - "resolved": "https://registry.npmjs.org/deferred/-/deferred-0.7.11.tgz", - "integrity": "sha512-8eluCl/Blx4YOGwMapBvXRKxHXhA8ejDXYzEaK8+/gtcm8hRMhSLmXSqDmNUKNc/C8HNSmuyyp/hflhqDAvK2A==", + "license": "ISC", "peer": true, "dependencies": { "d": "^1.0.1", @@ -14125,8 +13609,7 @@ }, "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -14141,8 +13624,7 @@ }, "node_modules/define-lazy-prop": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -14150,8 +13632,7 @@ }, "node_modules/define-properties": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -14210,8 +13691,7 @@ }, "node_modules/desm": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/desm/-/desm-1.3.0.tgz", - "integrity": "sha512-RvlHN2gfYA0BpCfjpWzCdQeR6p5U+84f5DzcirLow86UA/OcpwuOqXRC4Oz0bG9rzcJPVtMT6ZgNtjp4qh+uqA==", + "license": "MIT", "peer": true }, "node_modules/detect-indent": { @@ -14232,13 +13712,11 @@ }, "node_modules/devtools-protocol": { "version": "0.0.869402", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.869402.tgz", - "integrity": "sha512-VvlVYY+VDJe639yHs5PHISzdWTLL3Aw8rO4cvUtwvoxFd6FHbE4OpHHcde52M6096uYYazAmd4l0o5VuFRO2WA==" + "license": "BSD-3-Clause" }, "node_modules/dezalgo": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "license": "ISC", "peer": true, "dependencies": { "asap": "^2.0.0", @@ -14300,8 +13778,7 @@ }, "node_modules/dom-serializer": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -14331,8 +13808,7 @@ }, "node_modules/domhandler": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" }, @@ -14345,8 +13821,7 @@ }, "node_modules/domutils": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -14372,8 +13847,7 @@ }, "node_modules/dotenv": { "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=12" @@ -14381,8 +13855,7 @@ }, "node_modules/dotenv-expand": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-9.0.0.tgz", - "integrity": "sha512-uW8Hrhp5ammm9x7kBLR6jDfujgaDarNA02tprvZdyrJ7MpdzD1KyrIHG4l+YoC2fJ2UcdFdNWNWIjt+sexBHJw==", + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=12" @@ -14430,8 +13903,7 @@ }, "node_modules/duration": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", - "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", + "license": "ISC", "peer": true, "dependencies": { "d": "1", @@ -14440,8 +13912,7 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT", "peer": true }, "node_modules/ecc-jsbn": { @@ -14457,9 +13928,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.747", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.747.tgz", - "integrity": "sha512-+FnSWZIAvFHbsNVmUxhEqWiaOiPMcfum1GQzlWCg/wLigVtshOsjXHyEFfmt6cFK6+HkS3QOJBv6/3OPumbBfw==" + "version": "1.4.749", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.749.tgz", + "integrity": "sha512-LRMMrM9ITOvue0PoBrvNIraVmuDbJV5QC9ierz/z5VilMdPOVMjOtpICNld3PuXuTZ3CHH/UPxX9gHhAPwi+0Q==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -14527,8 +13998,7 @@ }, "node_modules/endent": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", - "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "license": "MIT", "dependencies": { "dedent": "^0.7.0", "fast-json-parse": "^1.0.3", @@ -14589,8 +14059,7 @@ }, "node_modules/entities": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, @@ -14638,8 +14107,7 @@ }, "node_modules/es-abstract": { "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -14697,8 +14165,7 @@ }, "node_modules/es-define-property": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -14708,16 +14175,14 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-object-atoms": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -14727,8 +14192,7 @@ }, "node_modules/es-set-tostringtag": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -14740,9 +14204,8 @@ }, "node_modules/es-shim-unscopables": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", "dev": true, + "license": "MIT", "dependencies": { "has": "^1.0.3" } @@ -14764,9 +14227,8 @@ }, "node_modules/es5-ext": { "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", "hasInstallScript": true, + "license": "ISC", "peer": true, "dependencies": { "es6-iterator": "^2.0.3", @@ -14779,8 +14241,7 @@ }, "node_modules/es6-iterator": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "license": "MIT", "peer": true, "dependencies": { "d": "1", @@ -14794,8 +14255,7 @@ }, "node_modules/es6-set": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.6.tgz", - "integrity": "sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==", + "license": "ISC", "peer": true, "dependencies": { "d": "^1.0.1", @@ -14811,8 +14271,7 @@ }, "node_modules/es6-symbol": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "license": "ISC", "peer": true, "dependencies": { "d": "^1.0.1", @@ -14821,8 +14280,7 @@ }, "node_modules/es6-weak-map": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "license": "ISC", "peer": true, "dependencies": { "d": "1", @@ -14831,6 +14289,43 @@ "es6-symbol": "^3.1.1" } }, + "node_modules/esbuild": { + "version": "0.19.12", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, "node_modules/escalade": { "version": "3.1.1", "license": "MIT", @@ -14862,9 +14357,8 @@ }, "node_modules/eslint": { "version": "8.37.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", - "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", @@ -14919,9 +14413,8 @@ }, "node_modules/eslint-config-prettier": { "version": "8.8.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", - "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -14931,9 +14424,8 @@ }, "node_modules/eslint-import-resolver-node": { "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.11.0", @@ -14942,18 +14434,16 @@ }, "node_modules/eslint-import-resolver-node/node_modules/debug": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-module-utils": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -14968,18 +14458,16 @@ }, "node_modules/eslint-module-utils/node_modules/debug": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import": { "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -15006,9 +14494,8 @@ }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -15026,9 +14513,8 @@ }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -15043,9 +14529,8 @@ }, "node_modules/eslint-scope": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -15094,9 +14579,8 @@ }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -15107,9 +14591,8 @@ }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15119,18 +14602,16 @@ }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -15173,8 +14654,7 @@ }, "node_modules/esniff": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-1.1.0.tgz", - "integrity": "sha512-vmHXOeOt7FJLsqofvFk4WB3ejvcHizCd8toXXwADmYfd02p2QwHRgkUbhYDX54y08nqk818CUTWipgZGlyN07g==", + "license": "MIT", "peer": true, "dependencies": { "d": "1", @@ -15183,9 +14663,8 @@ }, "node_modules/espree": { "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", @@ -15200,9 +14679,8 @@ }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15223,9 +14701,8 @@ }, "node_modules/esquery": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -15260,8 +14737,7 @@ }, "node_modules/essentials": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/essentials/-/essentials-1.2.0.tgz", - "integrity": "sha512-kP/j7Iw7KeNE8b/o7+tr9uX2s1wegElGOoGZ2Xm35qBr4BbbEcH3/bxR2nfH9l9JANCq9AUrvKw+gRuHtZp0HQ==", + "license": "ISC", "peer": true, "dependencies": { "uni-global": "^1.0.0" @@ -15284,8 +14760,7 @@ }, "node_modules/event-emitter": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", "peer": true, "dependencies": { "d": "1", @@ -15294,8 +14769,7 @@ }, "node_modules/event-target-shim": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -15447,8 +14921,7 @@ }, "node_modules/ext": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", "peer": true, "dependencies": { "type": "^2.7.2" @@ -15456,8 +14929,7 @@ }, "node_modules/ext-list": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "license": "MIT", "peer": true, "dependencies": { "mime-db": "^1.28.0" @@ -15468,8 +14940,7 @@ }, "node_modules/ext-name": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "license": "MIT", "peer": true, "dependencies": { "ext-list": "^2.0.0", @@ -15576,8 +15047,7 @@ }, "node_modules/extract-zip": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -15595,8 +15065,7 @@ }, "node_modules/extract-zip/node_modules/get-stream": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", "dependencies": { "pump": "^3.0.0" }, @@ -15622,8 +15091,7 @@ }, "node_modules/fast-copy": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==", + "license": "MIT", "peer": true }, "node_modules/fast-deep-equal": { @@ -15646,8 +15114,7 @@ }, "node_modules/fast-json-parse": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", - "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==" + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", @@ -15660,8 +15127,7 @@ }, "node_modules/fast-redact": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", - "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -15672,8 +15138,7 @@ }, "node_modules/fast-xml-parser": { "version": "4.0.11", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz", - "integrity": "sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==", + "license": "MIT", "dependencies": { "strnum": "^1.0.5" }, @@ -15687,8 +15152,7 @@ }, "node_modules/fastest-levenshtein": { "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "license": "MIT", "engines": { "node": ">= 4.9.1" } @@ -15720,8 +15184,6 @@ }, "node_modules/fetch-blob": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "funding": [ { "type": "github", @@ -15732,6 +15194,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "peer": true, "dependencies": { "node-domexception": "^1.0.0", @@ -15778,8 +15241,7 @@ }, "node_modules/file-type": { "version": "16.5.4", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", - "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "license": "MIT", "peer": true, "dependencies": { "readable-web-to-node-stream": "^3.0.0", @@ -15800,16 +15262,14 @@ }, "node_modules/file-url": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", - "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/filename-reserved-regex": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -15817,8 +15277,7 @@ }, "node_modules/filenamify": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "license": "MIT", "peer": true, "dependencies": { "filename-reserved-regex": "^2.0.0", @@ -15834,8 +15293,7 @@ }, "node_modules/filesize": { "version": "10.0.6", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.0.6.tgz", - "integrity": "sha512-rzpOZ4C9vMFDqOa6dNpog92CoLYjD79dnjLk2TYDDtImRIyLTOzqojCb05Opd1WuiWjs+fshhCgTd8cl7y5t+g==", + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">= 10.4.0" @@ -15971,8 +15429,7 @@ }, "node_modules/find-requires": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-requires/-/find-requires-1.0.0.tgz", - "integrity": "sha512-UME7hNwBfzeISSFQcBEDemEEskpOjI/shPrpJM5PI4DSdn6hX0dmz+2dL70blZER2z8tSnTRL+2rfzlYgtbBoQ==", + "license": "ISC", "peer": true, "dependencies": { "es5-ext": "^0.10.49", @@ -16086,8 +15543,7 @@ }, "node_modules/for-each": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } @@ -16120,8 +15576,7 @@ }, "node_modules/formdata-polyfill": { "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", "peer": true, "dependencies": { "fetch-blob": "^3.1.2" @@ -16241,8 +15696,7 @@ }, "node_modules/fs2": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/fs2/-/fs2-0.3.9.tgz", - "integrity": "sha512-WsOqncODWRlkjwll+73bAxVW3JPChDgaPX3DT4iTTm73UmG4VgALa7LaFblP232/DN60itkOrPZ8kaP1feksGQ==", + "license": "ISC", "peer": true, "dependencies": { "d": "^1.0.1", @@ -16270,16 +15724,14 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/function.prototype.name": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -16300,8 +15752,7 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16347,8 +15798,7 @@ }, "node_modules/get-intrinsic": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -16403,8 +15853,7 @@ }, "node_modules/get-stdin": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -16425,8 +15874,7 @@ }, "node_modules/get-symbol-description": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -16512,9 +15960,8 @@ }, "node_modules/globals": { "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -16527,8 +15974,7 @@ }, "node_modules/globalthis": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "license": "MIT", "dependencies": { "define-properties": "^1.1.3" }, @@ -16559,8 +16005,7 @@ }, "node_modules/gopd": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -16610,8 +16055,7 @@ }, "node_modules/graphlib": { "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "license": "MIT", "peer": true, "dependencies": { "lodash": "^4.17.15" @@ -16697,8 +16141,7 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -16708,8 +16151,7 @@ }, "node_modules/has-proto": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -16729,8 +16171,7 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -16846,8 +16287,7 @@ }, "node_modules/hasown": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -16864,8 +16304,7 @@ }, "node_modules/help-me": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", + "license": "MIT", "peer": true, "dependencies": { "glob": "^8.0.0", @@ -16874,8 +16313,7 @@ }, "node_modules/help-me/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0" @@ -16883,8 +16321,7 @@ }, "node_modules/help-me/node_modules/glob": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "license": "ISC", "peer": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -16902,8 +16339,7 @@ }, "node_modules/help-me/node_modules/minimatch": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", "peer": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -16925,8 +16361,7 @@ }, "node_modules/hexoid": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -16934,8 +16369,7 @@ }, "node_modules/highlight.js": { "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "license": "BSD-3-Clause", "engines": { "node": "*" } @@ -16951,8 +16385,6 @@ }, "node_modules/hogan.js": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", - "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", "dependencies": { "mkdirp": "0.3.0", "nopt": "1.0.10" @@ -16963,25 +16395,19 @@ }, "node_modules/hogan.js/node_modules/mkdirp": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "license": "MIT/X11", "engines": { "node": "*" } }, "node_modules/hogan.js/node_modules/nopt": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "license": "MIT", "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" } }, "node_modules/hook-std": { @@ -16993,8 +16419,7 @@ }, "node_modules/hoopy": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", - "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "license": "MIT", "engines": { "node": ">= 6.0.0" } @@ -17025,8 +16450,7 @@ }, "node_modules/html_codesniffer": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/html_codesniffer/-/html_codesniffer-2.5.1.tgz", - "integrity": "sha512-vcz0yAaX/OaV6sdNHuT9alBOKkSxYb8h5Yq26dUqgi7XmCgGUSa7U9PiY1PBXQFMjKv1wVPs5/QzHlGuxPDUGg==", + "license": "BSD-3-Clause", "engines": { "node": ">=6" } @@ -17038,8 +16462,6 @@ }, "node_modules/htmlparser2": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", - "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -17047,6 +16469,7 @@ "url": "https://github.com/sponsors/fb55" } ], + "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -17056,22 +16479,7 @@ }, "node_modules/http-cache-semantics": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "node_modules/http-errors": { - "version": "1.8.1", - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } + "license": "BSD-2-Clause" }, "node_modules/http-proxy": { "version": "1.18.1", @@ -17112,8 +16520,7 @@ }, "node_modules/http2-wrapper": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", "peer": true, "dependencies": { "quick-lru": "^5.1.1", @@ -17125,8 +16532,7 @@ }, "node_modules/http2-wrapper/node_modules/quick-lru": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -17271,14 +16677,12 @@ }, "node_modules/immediate": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT", "peer": true }, "node_modules/import-cwd": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", - "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", + "license": "MIT", "dependencies": { "import-from": "^3.0.0" }, @@ -17288,8 +16692,7 @@ }, "node_modules/import-cwd/node_modules/import-from": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", - "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -17465,8 +16868,7 @@ }, "node_modules/internal-slot": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -17500,8 +16902,7 @@ }, "node_modules/is": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", - "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", + "license": "MIT", "engines": { "node": "*" } @@ -17543,8 +16944,7 @@ }, "node_modules/is-array-buffer": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -17600,8 +17000,7 @@ }, "node_modules/is-callable": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -17622,8 +17021,7 @@ }, "node_modules/is-core-module": { "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "license": "MIT", "dependencies": { "has": "^1.0.3" }, @@ -17653,8 +17051,7 @@ }, "node_modules/is-data-view": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "license": "MIT", "dependencies": { "is-typed-array": "^1.1.13" }, @@ -17699,8 +17096,7 @@ }, "node_modules/is-docker": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", "peer": true, "bin": { "is-docker": "cli.js" @@ -17735,15 +17131,15 @@ }, "node_modules/is-generator-fn": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "engines": { "node": ">=6" } }, "node_modules/is-generator-function": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "license": "MIT", "peer": true, "dependencies": { "has-tostringtag": "^1.0.0" @@ -17804,8 +17200,7 @@ }, "node_modules/is-interactive": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -17817,14 +17212,12 @@ }, "node_modules/is-natural-number": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==", + "license": "MIT", "peer": true }, "node_modules/is-negative-zero": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -17893,14 +17286,12 @@ }, "node_modules/is-promise": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT", "peer": true }, "node_modules/is-regex": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -17928,8 +17319,7 @@ }, "node_modules/is-shared-array-buffer": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7" }, @@ -17989,8 +17379,7 @@ }, "node_modules/is-typed-array": { "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "license": "MIT", "dependencies": { "which-typed-array": "^1.1.14" }, @@ -18100,8 +17489,7 @@ }, "node_modules/isomorphic-ws": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", "peer": true, "peerDependencies": { "ws": "*" @@ -18223,8 +17611,7 @@ }, "node_modules/java-invoke-local": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/java-invoke-local/-/java-invoke-local-0.0.6.tgz", - "integrity": "sha512-gZmQKe1QrfkkMjCn8Qv9cpyJFyogTYqkP5WCobX5RNaHsJzIV/6NvAnlnouOcwKr29QrxLGDGcqYuJ+ae98s1A==", + "license": "MIT", "peer": true, "bin": { "java-invoke-local": "lib/cli.js" @@ -18519,9 +17906,9 @@ } }, "node_modules/jest-circus/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-cli": { "version": "29.7.0", @@ -18696,9 +18083,9 @@ } }, "node_modules/jest-cli/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-cli/node_modules/ts-node": { "version": "10.9.2", @@ -18847,9 +18234,9 @@ } }, "node_modules/jest-each/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-environment-node": { "version": "29.7.0", @@ -19000,9 +18387,9 @@ } }, "node_modules/jest-environment-node/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-get-type": { "version": "27.5.1", @@ -19111,9 +18498,9 @@ } }, "node_modules/jest-leak-detector/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-matcher-utils": { "version": "27.5.1", @@ -19193,8 +18580,9 @@ } }, "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "license": "MIT", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "engines": { "node": ">=6" }, @@ -19440,9 +18828,9 @@ } }, "node_modules/jest-runner/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-runner/node_modules/source-map-support": { "version": "0.5.13", @@ -19632,9 +19020,9 @@ } }, "node_modules/jest-runtime/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-snapshot": { "version": "29.7.0", @@ -19810,9 +19198,9 @@ } }, "node_modules/jest-snapshot/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-snapshot/node_modules/semver": { "version": "7.6.0", @@ -19930,9 +19318,9 @@ } }, "node_modules/jest-validate/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", + "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" }, "node_modules/jest-watcher": { "version": "29.7.0", @@ -20042,8 +19430,7 @@ }, "node_modules/jmespath": { "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "license": "Apache-2.0", "peer": true, "engines": { "node": ">= 0.6.0" @@ -20051,8 +19438,7 @@ }, "node_modules/jose": { "version": "4.11.2", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.11.2.tgz", - "integrity": "sha512-njj0VL2TsIxCtgzhO+9RRobBvws4oYyCM8TpvoUQwl/MbIM3NFJRR9+e6x0sS5xXaP1t6OCBkaBME98OV9zU5A==", + "license": "MIT", "peer": true, "funding": { "url": "https://github.com/sponsors/panva" @@ -20060,8 +19446,7 @@ }, "node_modules/joycon": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -20069,14 +19454,12 @@ }, "node_modules/jpeg-js": { "version": "0.4.4", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + "license": "BSD-3-Clause" }, "node_modules/js-sdsl": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", "dev": true, + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" @@ -20084,8 +19467,7 @@ }, "node_modules/js-string-escape": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "license": "MIT", "peer": true, "engines": { "node": ">= 0.8" @@ -20126,8 +19508,7 @@ }, "node_modules/json-cycle": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/json-cycle/-/json-cycle-1.3.0.tgz", - "integrity": "sha512-FD/SedD78LCdSvJaOUQAXseT8oQBb5z6IVYaQaCrVUlu9zOAr1BDdKyVYQaSD/GDsAMrXpKcOyBD4LIl8nfjHw==", + "license": "MIT", "peer": true, "engines": { "node": ">= 4" @@ -20143,8 +19524,7 @@ }, "node_modules/json-refs": { "version": "3.0.15", - "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-3.0.15.tgz", - "integrity": "sha512-0vOQd9eLNBL18EGl5yYaO44GhixmImes2wiYn9Z3sag3QnehWrYWlB9AFtMxCL2Bj3fyxgDYkxGFEU/chlYssw==", + "license": "MIT", "peer": true, "dependencies": { "commander": "~4.1.1", @@ -20165,8 +19545,7 @@ }, "node_modules/json-refs/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", "peer": true, "dependencies": { "sprintf-js": "~1.0.2" @@ -20174,8 +19553,7 @@ }, "node_modules/json-refs/node_modules/commander": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", "peer": true, "engines": { "node": ">= 6" @@ -20183,8 +19561,7 @@ }, "node_modules/json-refs/node_modules/js-yaml": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -20213,8 +19590,7 @@ }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -20251,8 +19627,7 @@ }, "node_modules/jsonpath-plus": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-7.2.0.tgz", - "integrity": "sha512-zBfiUPM5nD0YZSBT/o/fbCUlCcepMIdP0CJZxM1+KgA4f2T206f6VAg9e7mX35+KlMaIc5qXW34f3BnwJ3w+RA==", + "license": "MIT", "peer": true, "engines": { "node": ">=12.0.0" @@ -20271,8 +19646,7 @@ }, "node_modules/jsonschema": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "license": "MIT", "peer": true, "engines": { "node": "*" @@ -20308,8 +19682,7 @@ }, "node_modules/jszip": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", "peer": true, "dependencies": { "lie": "~3.3.0", @@ -20320,8 +19693,7 @@ }, "node_modules/jszip/node_modules/readable-stream": { "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "license": "MIT", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -20335,8 +19707,7 @@ }, "node_modules/jszip/node_modules/string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -20344,8 +19715,7 @@ }, "node_modules/jwt-decode": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", - "integrity": "sha512-86GgN2vzfUu7m9Wcj63iUkuDzFNYFVmjeDm2GzWpUk+opB0pEpMsw6ePCMrhYkumz2C1ihqtZzOMAg7FiXcNoQ==", + "license": "MIT", "peer": true }, "node_modules/keyv": { @@ -20435,7 +19805,8 @@ }, "node_modules/leven": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "engines": { "node": ">=6" } @@ -20454,8 +19825,7 @@ }, "node_modules/libnpmpack": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/libnpmpack/-/libnpmpack-3.1.0.tgz", - "integrity": "sha512-dO0ER8L6TPINOSyCAy/XTwsKIz42Bg+SB1XX9zCoaHimP7oqzV7O8PJGoPfEduLt8zidwu8oNW3nYrA43M6VCQ==", + "license": "ISC", "dependencies": { "@npmcli/run-script": "^2.0.0", "npm-package-arg": "^8.1.0", @@ -20467,8 +19837,7 @@ }, "node_modules/libnpmpack/node_modules/@npmcli/git": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", - "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", + "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^1.3.2", "lru-cache": "^6.0.0", @@ -20482,8 +19851,7 @@ }, "node_modules/libnpmpack/node_modules/ignore-walk": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", - "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", + "license": "ISC", "dependencies": { "minimatch": "^3.0.4" }, @@ -20493,8 +19861,7 @@ }, "node_modules/libnpmpack/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -20504,8 +19871,7 @@ }, "node_modules/libnpmpack/node_modules/npm-install-checks": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", - "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, @@ -20515,8 +19881,7 @@ }, "node_modules/libnpmpack/node_modules/npm-packlist": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", - "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", + "license": "ISC", "dependencies": { "glob": "^7.1.6", "ignore-walk": "^4.0.1", @@ -20532,8 +19897,7 @@ }, "node_modules/libnpmpack/node_modules/npm-pick-manifest": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", - "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", + "license": "ISC", "dependencies": { "npm-install-checks": "^4.0.0", "npm-normalize-package-bin": "^1.0.1", @@ -20543,8 +19907,7 @@ }, "node_modules/libnpmpack/node_modules/pacote": { "version": "12.0.3", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-12.0.3.tgz", - "integrity": "sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow==", + "license": "ISC", "dependencies": { "@npmcli/git": "^2.1.0", "@npmcli/installed-package-contents": "^1.0.6", @@ -20575,8 +19938,7 @@ }, "node_modules/libnpmpack/node_modules/tar": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -20591,16 +19953,14 @@ }, "node_modules/libnpmpack/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", "engines": { "node": ">=8" } }, "node_modules/libnpmpack/node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -20613,13 +19973,11 @@ }, "node_modules/libnpmpack/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/libnpmpublish": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-5.0.1.tgz", - "integrity": "sha512-S9HvvO8kGWWuGFvAQyw0T5NWxib21ktA1REGTB7I+GBqDjyYOjjwzJaavtTxDD8ID18dKCluOXg0PdMmRdKfHA==", + "license": "ISC", "dependencies": { "normalize-package-data": "^3.0.2", "npm-package-arg": "^8.1.2", @@ -20633,8 +19991,7 @@ }, "node_modules/lie": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", "peer": true, "dependencies": { "immediate": "~3.0.5" @@ -20801,6 +20158,14 @@ "node": ">=8" } }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/loader-runner": { "version": "2.4.0", "license": "MIT", @@ -20810,8 +20175,7 @@ }, "node_modules/loader-utils": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "license": "MIT", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -20823,8 +20187,7 @@ }, "node_modules/loader-utils/node_modules/json5": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -20902,8 +20265,7 @@ }, "node_modules/log": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/log/-/log-6.3.1.tgz", - "integrity": "sha512-McG47rJEWOkXTDioZzQNydAVvZNeEkSyLJ1VWkFwfW+o1knW+QSi8D1KjPn/TnctV+q99lkvJNe1f0E1IjfY2A==", + "license": "ISC", "peer": true, "dependencies": { "d": "^1.0.1", @@ -20917,8 +20279,7 @@ }, "node_modules/log-node": { "version": "8.0.3", - "resolved": "https://registry.npmjs.org/log-node/-/log-node-8.0.3.tgz", - "integrity": "sha512-1UBwzgYiCIDFs8A0rM2QdBFo8Wd8UQ0HrSTu/MNI+/2zN3NoHRj2fhplurAyuxTYUXu3Oohugq1jAn5s05u1MQ==", + "license": "ISC", "peer": true, "dependencies": { "ansi-regex": "^5.0.1", @@ -20939,8 +20300,7 @@ }, "node_modules/log-node/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -21037,8 +20397,7 @@ }, "node_modules/long-timeout": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", - "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==", + "license": "MIT", "peer": true }, "node_modules/loupe": { @@ -21068,8 +20427,7 @@ }, "node_modules/lru-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "license": "MIT", "peer": true, "dependencies": { "es5-ext": "~0.10.2" @@ -21077,8 +20435,7 @@ }, "node_modules/luxon": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.2.1.tgz", - "integrity": "sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg==", + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -21113,8 +20470,7 @@ }, "node_modules/make-fetch-happen": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -21139,8 +20495,7 @@ }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -21150,8 +20505,7 @@ }, "node_modules/make-fetch-happen/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/makeerror": { "version": "1.0.12", @@ -21199,8 +20553,7 @@ }, "node_modules/memoizee": { "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "license": "ISC", "peer": true, "dependencies": { "d": "^1.0.1", @@ -21432,8 +20785,7 @@ }, "node_modules/minipass-fetch": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", "dependencies": { "minipass": "^3.1.0", "minipass-sized": "^1.0.3", @@ -21593,8 +20945,7 @@ }, "node_modules/mkdirp-classic": { "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + "license": "MIT" }, "node_modules/mocha": { "version": "8.4.0", @@ -21910,8 +21261,7 @@ }, "node_modules/mz": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -22030,8 +21380,7 @@ }, "node_modules/native-promise-only": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==", + "license": "MIT", "peer": true }, "node_modules/natural-compare": { @@ -22040,14 +21389,12 @@ }, "node_modules/natural-compare-lite": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ncjsm": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ncjsm/-/ncjsm-4.3.2.tgz", - "integrity": "sha512-6d1VWA7FY31CpI4Ki97Fpm36jfURkVbpktizp8aoVViTZRQgr/0ddmlKerALSSlzfwQRBeSq1qwwVcBJK4Sk7Q==", + "license": "ISC", "peer": true, "dependencies": { "builtin-modules": "^3.3.0", @@ -22089,14 +21436,12 @@ }, "node_modules/next-tick": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC", "peer": true }, "node_modules/nice-try": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "license": "MIT", "peer": true }, "node_modules/node-bitmap": { @@ -22107,8 +21452,7 @@ }, "node_modules/node-dir": { "version": "0.1.17", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", - "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "license": "MIT", "peer": true, "dependencies": { "minimatch": "^3.0.2" @@ -22119,8 +21463,6 @@ }, "node_modules/node-domexception": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "funding": [ { "type": "github", @@ -22131,6 +21473,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "peer": true, "engines": { "node": ">=10.5.0" @@ -22138,8 +21481,7 @@ }, "node_modules/node-fetch": { "version": "2.6.8", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", - "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -22173,8 +21515,7 @@ }, "node_modules/node-gyp": { "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -22196,16 +21537,14 @@ }, "node_modules/node-gyp/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", "engines": { "node": ">=8" } }, "node_modules/node-gyp/node_modules/tar": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -22220,8 +21559,7 @@ }, "node_modules/node-gyp/node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -22234,14 +21572,12 @@ }, "node_modules/node-gyp/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/node-html-parser": { "version": "6.1.4", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.4.tgz", - "integrity": "sha512-3muP9Uy/Pz7bQa9TNYVQzWJhNZMqyCx7xJle8kz2/y1UgzAUyXXShc1IcPaJy6u07CE3K5rQcRwlvHzmlySRjg==", "dev": true, + "license": "MIT", "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" @@ -22322,8 +21658,7 @@ }, "node_modules/node-schedule": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", - "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==", + "license": "MIT", "peer": true, "dependencies": { "cron-parser": "^4.2.0", @@ -22336,8 +21671,7 @@ }, "node_modules/node.extend": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.2.tgz", - "integrity": "sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==", + "license": "(MIT OR GPL-2.0)", "dependencies": { "has": "^1.0.3", "is": "^3.2.1" @@ -22648,8 +21982,7 @@ }, "node_modules/npm-registry-fetch": { "version": "12.0.2", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-12.0.2.tgz", - "integrity": "sha512-Df5QT3RaJnXYuOwtXBXS9BWs+tHH2olvkCLh6jcR/b/u3DvPMlp3J0TvvYwplPKxHMOwfg287PYih9QqaVFoKA==", + "license": "ISC", "dependencies": { "make-fetch-happen": "^10.0.1", "minipass": "^3.1.6", @@ -22664,8 +21997,7 @@ }, "node_modules/npm-registry-fetch/node_modules/@npmcli/fs": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "license": "ISC", "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" @@ -22676,9 +22008,7 @@ }, "node_modules/npm-registry-fetch/node_modules/@npmcli/move-file": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -22689,24 +22019,21 @@ }, "node_modules/npm-registry-fetch/node_modules/@tootallnate/once": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/npm-registry-fetch/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/npm-registry-fetch/node_modules/cacache": { "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "license": "ISC", "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", @@ -22733,8 +22060,7 @@ }, "node_modules/npm-registry-fetch/node_modules/glob": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -22751,8 +22077,7 @@ }, "node_modules/npm-registry-fetch/node_modules/http-proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -22764,16 +22089,14 @@ }, "node_modules/npm-registry-fetch/node_modules/lru-cache": { "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", "engines": { "node": ">=12" } }, "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "license": "ISC", "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", @@ -22798,8 +22121,7 @@ }, "node_modules/npm-registry-fetch/node_modules/make-fetch-happen/node_modules/minipass-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "license": "MIT", "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -22814,8 +22136,7 @@ }, "node_modules/npm-registry-fetch/node_modules/minimatch": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -22825,8 +22146,7 @@ }, "node_modules/npm-registry-fetch/node_modules/socks-proxy-agent": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "license": "MIT", "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -22838,8 +22158,7 @@ }, "node_modules/npm-registry-fetch/node_modules/ssri": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "license": "ISC", "dependencies": { "minipass": "^3.1.1" }, @@ -22849,8 +22168,7 @@ }, "node_modules/npm-registry-fetch/node_modules/tar": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -22865,16 +22183,14 @@ }, "node_modules/npm-registry-fetch/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", "engines": { "node": ">=8" } }, "node_modules/npm-registry-fetch/node_modules/unique-filename": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "license": "ISC", "dependencies": { "unique-slug": "^3.0.0" }, @@ -22884,8 +22200,7 @@ }, "node_modules/npm-registry-fetch/node_modules/unique-slug": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -22895,13 +22210,11 @@ }, "node_modules/npm-registry-fetch/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "node_modules/npm-registry-utilities": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-registry-utilities/-/npm-registry-utilities-1.0.0.tgz", - "integrity": "sha512-9xYfSJy2IFQw1i6462EJzjChL9e65EfSo2Cw6kl0EFeDp05VvU+anrQk3Fc0d1MbVCq7rWIxeer89O9SUQ/uOg==", + "license": "ISC", "peer": true, "dependencies": { "ext": "^1.6.0", @@ -22995,8 +22308,7 @@ }, "node_modules/object-hash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", "peer": true, "engines": { "node": ">= 6" @@ -23004,8 +22316,7 @@ }, "node_modules/object-inspect": { "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -23029,8 +22340,7 @@ }, "node_modules/object.assign": { "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -23046,8 +22356,7 @@ }, "node_modules/object.hasown": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "license": "MIT", "peer": true, "dependencies": { "define-properties": "^1.1.4", @@ -23069,9 +22378,8 @@ }, "node_modules/object.values": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -23086,8 +22394,7 @@ }, "node_modules/objectorarray": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", - "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==" + "license": "ISC" }, "node_modules/omggif": { "version": "1.0.10", @@ -23095,8 +22402,7 @@ }, "node_modules/on-exit-leak-free": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -23140,8 +22446,7 @@ }, "node_modules/open": { "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "license": "MIT", "peer": true, "dependencies": { "define-lazy-prop": "^2.0.0", @@ -23157,8 +22462,7 @@ }, "node_modules/open/node_modules/is-wsl": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", "peer": true, "dependencies": { "is-docker": "^2.0.0" @@ -23192,8 +22496,7 @@ }, "node_modules/ora": { "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", "peer": true, "dependencies": { "bl": "^4.1.0", @@ -23242,8 +22545,7 @@ }, "node_modules/p-event": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", - "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "license": "MIT", "peer": true, "dependencies": { "p-timeout": "^3.1.0" @@ -23303,8 +22605,7 @@ }, "node_modules/p-memoize": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-7.1.1.tgz", - "integrity": "sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA==", + "license": "MIT", "peer": true, "dependencies": { "mimic-fn": "^4.0.0", @@ -23319,8 +22620,7 @@ }, "node_modules/p-memoize/node_modules/mimic-fn": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -23381,8 +22681,7 @@ }, "node_modules/pa11y": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/pa11y/-/pa11y-6.1.1.tgz", - "integrity": "sha512-2NzqA3D9CUlDWj8WuOI4fM2P0qM1d/IUxsRRpzCOfDT5eMR1oEgmUwW2TAk+f90ff/GVck0BewdYT4et4BANew==", + "license": "LGPL-3.0", "dependencies": { "axe-core": "^4.0.2", "bfj": "~7.0.2", @@ -23405,8 +22704,7 @@ }, "node_modules/pa11y-ci": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pa11y-ci/-/pa11y-ci-3.0.1.tgz", - "integrity": "sha512-DUtEIhEG3Ofds7qRuplq0DdCb9doILRlzcRctFNzo4QUNmVy4iZfM3u51A9cqoPo2irCJZoo5BzfiFrcriY2IQ==", + "license": "LGPL-3.0", "dependencies": { "async": "~2.6.3", "cheerio": "~1.0.0-rc.10", @@ -23429,8 +22727,7 @@ }, "node_modules/pa11y-ci/node_modules/array-union": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "license": "MIT", "dependencies": { "array-uniq": "^1.0.1" }, @@ -23440,16 +22737,14 @@ }, "node_modules/pa11y-ci/node_modules/async": { "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "license": "MIT", "dependencies": { "lodash": "^4.17.14" } }, "node_modules/pa11y-ci/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -23460,8 +22755,7 @@ }, "node_modules/pa11y-ci/node_modules/globby": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "license": "MIT", "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -23475,16 +22769,14 @@ }, "node_modules/pa11y-ci/node_modules/kleur": { "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pa11y-ci/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -23494,8 +22786,7 @@ }, "node_modules/pa11y-ci/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -23508,8 +22799,7 @@ }, "node_modules/pa11y-ci/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -23519,16 +22809,14 @@ }, "node_modules/pa11y-ci/node_modules/pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pa11y-ci/node_modules/pkg-dir": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -23538,10 +22826,8 @@ }, "node_modules/pa11y-ci/node_modules/puppeteer": { "version": "9.1.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-9.1.1.tgz", - "integrity": "sha512-W+nOulP2tYd/ZG99WuZC/I5ljjQQ7EUw/jQGcIb9eu8mDlZxNY2SgcJXTLG9h5gRvqA3uJOe4hZXYsd3EqioMw==", - "deprecated": "Version no longer supported. Upgrade to @latest", "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0", "devtools-protocol": "0.0.869402", @@ -23562,16 +22848,14 @@ }, "node_modules/pa11y/node_modules/commander": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.0.0.tgz", - "integrity": "sha512-Xvf85aAtu6v22+E5hfVoLHqyul/jyxh91zvqk/ioJTQuJR7Z78n7H558vMPKanPSRgIEeZemT92I2g9Y8LPbSQ==", + "license": "MIT", "engines": { "node": ">= 12" } }, "node_modules/pa11y/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -23582,16 +22866,14 @@ }, "node_modules/pa11y/node_modules/kleur": { "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pa11y/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -23601,8 +22883,7 @@ }, "node_modules/pa11y/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -23615,8 +22896,7 @@ }, "node_modules/pa11y/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -23626,16 +22906,14 @@ }, "node_modules/pa11y/node_modules/p-timeout": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz", - "integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==", + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/pa11y/node_modules/pkg-dir": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -23645,10 +22923,8 @@ }, "node_modules/pa11y/node_modules/puppeteer": { "version": "9.1.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-9.1.1.tgz", - "integrity": "sha512-W+nOulP2tYd/ZG99WuZC/I5ljjQQ7EUw/jQGcIb9eu8mDlZxNY2SgcJXTLG9h5gRvqA3uJOe4hZXYsd3EqioMw==", - "deprecated": "Version no longer supported. Upgrade to @latest", "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0", "devtools-protocol": "0.0.869402", @@ -24084,9 +23360,8 @@ }, "node_modules/parse-diff": { "version": "0.9.0", - "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.9.0.tgz", - "integrity": "sha512-Jn+VZORAezkfOXR6B40EZcXxdJBamtgBpfeoFH6hxD+p0e74nVaCL9SWlQj1ggc8b6AexgPKlDiiE0CMMZDSbQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/parse-github-repo-url": { "version": "1.4.1", @@ -24111,8 +23386,7 @@ }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "license": "MIT", "dependencies": { "domhandler": "^5.0.2", "parse5": "^7.0.0" @@ -24123,8 +23397,7 @@ }, "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", - "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "license": "MIT", "dependencies": { "entities": "^4.3.0" }, @@ -24186,8 +23459,7 @@ }, "node_modules/path-loader": { "version": "1.0.12", - "resolved": "https://registry.npmjs.org/path-loader/-/path-loader-1.0.12.tgz", - "integrity": "sha512-n7oDG8B+k/p818uweWrOixY9/Dsr89o2TkCm6tOTex3fpdo2+BFDgR+KpB37mGKBRsBAlR8CIJMFN0OEy/7hIQ==", + "license": "MIT", "peer": true, "dependencies": { "native-promise-only": "^0.8.1", @@ -24196,8 +23468,7 @@ }, "node_modules/path-loader/node_modules/form-data": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", "peer": true, "dependencies": { "asynckit": "^0.4.0", @@ -24210,8 +23481,7 @@ }, "node_modules/path-loader/node_modules/formidable": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.1.tgz", - "integrity": "sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==", + "license": "MIT", "peer": true, "dependencies": { "dezalgo": "^1.0.4", @@ -24225,8 +23495,7 @@ }, "node_modules/path-loader/node_modules/qs": { "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "license": "BSD-3-Clause", "peer": true, "dependencies": { "side-channel": "^1.0.4" @@ -24240,9 +23509,7 @@ }, "node_modules/path-loader/node_modules/superagent": { "version": "7.1.6", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.6.tgz", - "integrity": "sha512-gZkVCQR1gy/oUXr+kxJMLDjla434KmSOKbx5iGD30Ql+AkJQ/YlPKECJy2nhqOsHLjGHzoDTXNSjhnvWhzKk7g==", - "deprecated": "Please downgrade to v7.1.5 if you need IE/ActiveXObject support OR upgrade to v8.0.0 as we no longer support IE and published an incorrect patch version (see https://github.com/visionmedia/superagent/issues/1731)", + "license": "MIT", "peer": true, "dependencies": { "component-emitter": "^1.3.0", @@ -24274,8 +23541,7 @@ }, "node_modules/path2": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/path2/-/path2-0.1.0.tgz", - "integrity": "sha512-TX+cz8Jk+ta7IvRy2FAej8rdlbrP0+uBIkP/5DTODez/AuL/vSb30KuAdDxGVREXzn8QfAiu5mJYJ1XjbOhEPA==", + "license": "MIT", "peer": true }, "node_modules/pathval": { @@ -24302,8 +23568,7 @@ }, "node_modules/peek-readable": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", - "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -24344,16 +23609,14 @@ }, "node_modules/pinkie": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "license": "MIT", "dependencies": { "pinkie": "^2.0.0" }, @@ -24363,8 +23626,7 @@ }, "node_modules/pino": { "version": "8.15.4", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.15.4.tgz", - "integrity": "sha512-3s+SfSxeugMt8QeBVXprIJAgXuGDeGuHBfquXKEXKnpghlXzMGMjoa8tOSyzz00iBfQX3xlZvm2yJQ+d6SrVsg==", + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", @@ -24384,8 +23646,7 @@ }, "node_modules/pino-abstract-transport": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", - "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", + "license": "MIT", "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" @@ -24393,8 +23654,6 @@ }, "node_modules/pino-abstract-transport/node_modules/buffer": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -24409,6 +23668,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -24416,8 +23676,7 @@ }, "node_modules/pino-abstract-transport/node_modules/readable-stream": { "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -24431,16 +23690,14 @@ }, "node_modules/pino-abstract-transport/node_modules/split2": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", "engines": { "node": ">= 10.x" } }, "node_modules/pino-pretty": { "version": "10.2.2", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.2.2.tgz", - "integrity": "sha512-RvAdCQAU51MdVsJdvXX4Bipb52wwldXtOzlva1NT8q2d7tmgYWFIMLhoSnfx2Sr+Hi7BLGpR/n8wgrcq5G/ykA==", + "license": "MIT", "peer": true, "dependencies": { "colorette": "^2.0.7", @@ -24464,8 +23721,6 @@ }, "node_modules/pino-pretty/node_modules/buffer": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -24480,6 +23735,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "peer": true, "dependencies": { "base64-js": "^1.3.1", @@ -24488,8 +23744,7 @@ }, "node_modules/pino-pretty/node_modules/dateformat": { "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", "peer": true, "engines": { "node": "*" @@ -24497,8 +23752,7 @@ }, "node_modules/pino-pretty/node_modules/readable-stream": { "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "license": "MIT", "peer": true, "dependencies": { "abort-controller": "^3.0.0", @@ -24513,8 +23767,7 @@ }, "node_modules/pino-std-serializers": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", - "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" + "license": "MIT" }, "node_modules/pirates": { "version": "4.0.5", @@ -24563,8 +23816,7 @@ }, "node_modules/possible-typed-array-names": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -24587,8 +23839,7 @@ }, "node_modules/prettier": { "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "license": "MIT", "bin": { "prettier": "bin-prettier.js" }, @@ -24643,8 +23894,7 @@ }, "node_modules/process-utils": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/process-utils/-/process-utils-4.0.0.tgz", - "integrity": "sha512-fMyMQbKCxX51YxR7YGCzPjLsU3yDzXFkP4oi1/Mt5Ixnk7GO/7uUTj8mrCHUwuvozWzI+V7QSJR9cZYnwNOZPg==", + "license": "ISC", "peer": true, "dependencies": { "ext": "^1.4.0", @@ -24658,8 +23908,7 @@ }, "node_modules/process-warning": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz", - "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==" + "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", @@ -24674,8 +23923,7 @@ }, "node_modules/promise-queue": { "version": "2.2.5", - "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz", - "integrity": "sha512-p/iXrPSVfnqPft24ZdNNLECw/UrtLTpT3jpAAMzl/o5/rDsGCPo3/CQS2611flL6LkoEJ3oQZw7C8Q80ZISXRQ==", + "license": "MIT", "peer": true, "engines": { "node": ">= 0.8.0" @@ -24705,8 +23953,7 @@ }, "node_modules/protocolify": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/protocolify/-/protocolify-3.0.0.tgz", - "integrity": "sha512-PuvDJOkKJMVQx8jSNf8E5g0bJw/UTKm30mTjFHg4N30c8sefgA5Qr/f8INKqYBKfvP/MUSJrj+z1Smjbq4/3rQ==", + "license": "MIT", "dependencies": { "file-url": "^3.0.0", "prepend-http": "^3.0.0" @@ -24717,8 +23964,7 @@ }, "node_modules/protocolify/node_modules/prepend-http": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-3.0.1.tgz", - "integrity": "sha512-BLxfZh+m6UiAiCPZFJ4+vYoL7NrRs5XgCTRrjseATAggXhdZKKxn+JUNmuVYWY23bDHgaEHodxw8mnmtVEDtHw==", + "license": "MIT", "engines": { "node": ">=8" } @@ -24806,10 +24052,11 @@ }, "node_modules/puppeteer": { "version": "18.1.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-18.1.0.tgz", - "integrity": "sha512-2RCVWIF+pZOSfksWlQU0Hh6CeUT5NYt66CDDgRyuReu6EvBAk1y+/Q7DuzYNvGChSecGMb7QPN0hkxAa3guAog==", - "deprecated": "< 19.4.0 is no longer supported", "hasInstallScript": true, + "license": "Apache-2.0", + "workspaces": [ + "packages/*" + ], "dependencies": { "cross-fetch": "3.1.5", "debug": "4.3.4", @@ -24829,13 +24076,11 @@ }, "node_modules/puppeteer/node_modules/devtools-protocol": { "version": "0.0.1045489", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1045489.tgz", - "integrity": "sha512-D+PTmWulkuQW4D1NTiCRCFxF7pQPn0hgp4YyX4wAQ6xYXKOadSWPR3ENGDQ47MW/Ewc9v2rpC/UEEGahgBYpSQ==" + "license": "BSD-3-Clause" }, "node_modules/puppeteer/node_modules/ws": { "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -24915,8 +24160,7 @@ }, "node_modules/quick-format-unescaped": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + "license": "MIT" }, "node_modules/quick-lru": { "version": "4.0.1", @@ -25173,8 +24417,7 @@ }, "node_modules/readable-web-to-node-stream": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "license": "MIT", "peer": true, "dependencies": { "readable-stream": "^3.6.0" @@ -25189,8 +24432,7 @@ }, "node_modules/readdir-glob": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz", - "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", + "license": "Apache-2.0", "peer": true, "dependencies": { "minimatch": "^5.1.0" @@ -25198,8 +24440,7 @@ }, "node_modules/readdir-glob/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0" @@ -25207,8 +24448,7 @@ }, "node_modules/readdir-glob/node_modules/minimatch": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", "peer": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -25229,8 +24469,7 @@ }, "node_modules/real-require": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", "engines": { "node": ">= 12.13.0" } @@ -25330,8 +24569,7 @@ }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -25419,9 +24657,8 @@ }, "node_modules/release-please": { "version": "15.0.0", - "resolved": "https://registry.npmjs.org/release-please/-/release-please-15.0.0.tgz", - "integrity": "sha512-xNN/+xMuShbcpyLY0Gliu1OGHsz8gTNZzl/8V7i7BlphOJR9M0QTbp1vBxiBuy1IVm9NJEZ8DVytYXBGSguc3A==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@conventional-commits/parser": "^0.4.1", "@google-automations/git-file-utils": "^1.2.0", @@ -25467,9 +24704,8 @@ }, "node_modules/release-please/node_modules/@octokit/endpoint": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", - "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "is-plain-object": "^5.0.0", @@ -25481,15 +24717,13 @@ }, "node_modules/release-please/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", - "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/release-please/node_modules/@octokit/request": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", - "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -25504,9 +24738,8 @@ }, "node_modules/release-please/node_modules/@octokit/request-error": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", - "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "deprecation": "^2.0.0", @@ -25518,27 +24751,24 @@ }, "node_modules/release-please/node_modules/@octokit/types": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", - "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } }, "node_modules/release-please/node_modules/@tootallnate/once": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/release-please/node_modules/conventional-changelog-conventionalcommits": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", - "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", "dev": true, + "license": "ISC", "dependencies": { "compare-func": "^2.0.0", "lodash": "^4.17.15", @@ -25550,9 +24780,8 @@ }, "node_modules/release-please/node_modules/http-proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -25667,8 +24896,7 @@ }, "node_modules/resolve": { "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "license": "MIT", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -25683,8 +24911,7 @@ }, "node_modules/resolve-alpn": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT", "peer": true }, "node_modules/resolve-cwd": { @@ -25717,8 +24944,7 @@ }, "node_modules/resolve-pkg": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz", - "integrity": "sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==", + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -25849,8 +25075,6 @@ }, "node_modules/run-parallel-limit": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", - "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", "funding": [ { "type": "github", @@ -25865,6 +25089,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "peer": true, "dependencies": { "queue-microtask": "^1.2.2" @@ -25894,8 +25119,7 @@ }, "node_modules/safe-array-concat": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -25911,8 +25135,7 @@ }, "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "license": "MIT" }, "node_modules/safe-buffer": { "version": "5.1.2", @@ -25927,8 +25150,7 @@ }, "node_modules/safe-regex-test": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -25952,10 +25174,13 @@ "version": "2.1.2", "license": "MIT" }, + "node_modules/sandbox": { + "resolved": "core/sandbox", + "link": true + }, "node_modules/sax": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", + "license": "ISC", "peer": true }, "node_modules/scarlet": { @@ -25979,8 +25204,7 @@ }, "node_modules/secure-json-parse": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause", "peer": true }, "node_modules/seedrandom": { @@ -25989,8 +25213,7 @@ }, "node_modules/seek-bzip": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", - "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "license": "MIT", "peer": true, "dependencies": { "commander": "^2.8.1" @@ -26002,14 +25225,12 @@ }, "node_modules/seek-bzip/node_modules/commander": { "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT", "peer": true }, "node_modules/semver": { "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -26045,8 +25266,7 @@ }, "node_modules/semver-regex": { "version": "3.1.4", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", - "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -26087,9 +25307,8 @@ }, "node_modules/serverless": { "version": "3.27.0", - "resolved": "https://registry.npmjs.org/serverless/-/serverless-3.27.0.tgz", - "integrity": "sha512-+8EDo7x8IJxTj4KqQG71qpX7oq+EZy0NGm/04q3M5jK7L8rLowEtnzq82s93yeNSgmJSMopd3pTzuH9CCWkNMw==", "hasInstallScript": true, + "license": "MIT", "peer": true, "dependencies": { "@serverless/dashboard-plugin": "^6.2.3", @@ -26156,8 +25375,7 @@ }, "node_modules/serverless-offline": { "version": "12.0.4", - "resolved": "https://registry.npmjs.org/serverless-offline/-/serverless-offline-12.0.4.tgz", - "integrity": "sha512-G256wDHI12vE0CJ0uTJMBlfnaN7o7td4GgClvQtuedt/n7vKoUfN0och+LybD6YVGsR5h1xpYjPPPLy2QFqWaA==", + "license": "MIT", "peer": true, "dependencies": { "@aws-sdk/client-lambda": "^3.241.0", @@ -26196,14 +25414,12 @@ }, "node_modules/serverless-offline/node_modules/@types/retry": { "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", - "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", + "license": "MIT", "peer": true }, "node_modules/serverless-offline/node_modules/ansi-regex": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -26214,8 +25430,7 @@ }, "node_modules/serverless-offline/node_modules/ansi-styles": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -26226,8 +25441,7 @@ }, "node_modules/serverless-offline/node_modules/boxen": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.1.tgz", - "integrity": "sha512-8k2eH6SRAK00NDl1iX5q17RJ8rfl53TajdYxE3ssMLehbg487dEVgsad4pIsZb/QqBgYWIl6JOauMTLGX2Kpkw==", + "license": "MIT", "peer": true, "dependencies": { "ansi-align": "^3.0.1", @@ -26248,8 +25462,7 @@ }, "node_modules/serverless-offline/node_modules/camelcase": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "license": "MIT", "peer": true, "engines": { "node": ">=14.16" @@ -26260,8 +25473,7 @@ }, "node_modules/serverless-offline/node_modules/chalk": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "license": "MIT", "peer": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -26272,8 +25484,7 @@ }, "node_modules/serverless-offline/node_modules/cli-boxes": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -26284,8 +25495,7 @@ }, "node_modules/serverless-offline/node_modules/cross-spawn": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "license": "MIT", "peer": true, "dependencies": { "path-key": "^3.1.0", @@ -26298,8 +25508,7 @@ }, "node_modules/serverless-offline/node_modules/data-uri-to-buffer": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", "peer": true, "engines": { "node": ">= 12" @@ -26307,14 +25516,12 @@ }, "node_modules/serverless-offline/node_modules/emoji-regex": { "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT", "peer": true }, "node_modules/serverless-offline/node_modules/execa": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", - "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "license": "MIT", "peer": true, "dependencies": { "cross-spawn": "^7.0.3", @@ -26336,8 +25543,7 @@ }, "node_modules/serverless-offline/node_modules/fs-extra": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", - "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", + "license": "MIT", "peer": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -26350,8 +25556,7 @@ }, "node_modules/serverless-offline/node_modules/human-signals": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", - "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "license": "Apache-2.0", "peer": true, "engines": { "node": ">=12.20.0" @@ -26359,8 +25564,7 @@ }, "node_modules/serverless-offline/node_modules/is-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", "peer": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -26371,8 +25575,7 @@ }, "node_modules/serverless-offline/node_modules/is-wsl": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", "peer": true, "dependencies": { "is-docker": "^2.0.0" @@ -26383,8 +25586,7 @@ }, "node_modules/serverless-offline/node_modules/mimic-fn": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -26395,8 +25597,7 @@ }, "node_modules/serverless-offline/node_modules/node-fetch": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", - "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", + "license": "MIT", "peer": true, "dependencies": { "data-uri-to-buffer": "^4.0.0", @@ -26413,8 +25614,7 @@ }, "node_modules/serverless-offline/node_modules/npm-run-path": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "license": "MIT", "peer": true, "dependencies": { "path-key": "^4.0.0" @@ -26428,8 +25628,7 @@ }, "node_modules/serverless-offline/node_modules/npm-run-path/node_modules/path-key": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -26440,8 +25639,7 @@ }, "node_modules/serverless-offline/node_modules/onetime": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "license": "MIT", "peer": true, "dependencies": { "mimic-fn": "^4.0.0" @@ -26455,8 +25653,7 @@ }, "node_modules/serverless-offline/node_modules/p-retry": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-5.1.2.tgz", - "integrity": "sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==", + "license": "MIT", "peer": true, "dependencies": { "@types/retry": "0.12.1", @@ -26471,8 +25668,7 @@ }, "node_modules/serverless-offline/node_modules/retry": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", "peer": true, "engines": { "node": ">= 4" @@ -26480,8 +25676,7 @@ }, "node_modules/serverless-offline/node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "peer": true, "dependencies": { "shebang-regex": "^3.0.0" @@ -26492,8 +25687,7 @@ }, "node_modules/serverless-offline/node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -26501,8 +25695,7 @@ }, "node_modules/serverless-offline/node_modules/string-width": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", "peer": true, "dependencies": { "eastasianwidth": "^0.2.0", @@ -26518,8 +25711,7 @@ }, "node_modules/serverless-offline/node_modules/strip-ansi": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "license": "MIT", "peer": true, "dependencies": { "ansi-regex": "^6.0.1" @@ -26533,8 +25725,7 @@ }, "node_modules/serverless-offline/node_modules/strip-final-newline": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -26545,8 +25736,7 @@ }, "node_modules/serverless-offline/node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "peer": true, "dependencies": { "isexe": "^2.0.0" @@ -26560,8 +25750,7 @@ }, "node_modules/serverless-offline/node_modules/widest-line": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "license": "MIT", "peer": true, "dependencies": { "string-width": "^5.0.1" @@ -26575,8 +25764,7 @@ }, "node_modules/serverless-offline/node_modules/wrap-ansi": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", "peer": true, "dependencies": { "ansi-styles": "^6.1.0", @@ -26592,8 +25780,7 @@ }, "node_modules/serverless-offline/node_modules/ws": { "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", + "license": "MIT", "peer": true, "engines": { "node": ">=10.0.0" @@ -26613,8 +25800,7 @@ }, "node_modules/serverless/node_modules/@sindresorhus/is": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -26625,8 +25811,7 @@ }, "node_modules/serverless/node_modules/@szmarczak/http-timer": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", "peer": true, "dependencies": { "defer-to-connect": "^2.0.0" @@ -26637,8 +25822,7 @@ }, "node_modules/serverless/node_modules/ajv": { "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "license": "MIT", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -26653,8 +25837,7 @@ }, "node_modules/serverless/node_modules/archiver": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", - "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", + "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -26671,8 +25854,7 @@ }, "node_modules/serverless/node_modules/cacheable-request": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "license": "MIT", "peer": true, "dependencies": { "clone-response": "^1.0.2", @@ -26689,14 +25871,13 @@ }, "node_modules/serverless/node_modules/ci-info": { "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -26704,8 +25885,7 @@ }, "node_modules/serverless/node_modules/compress-commons": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", - "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "license": "MIT", "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", @@ -26719,8 +25899,7 @@ }, "node_modules/serverless/node_modules/crc32-stream": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", - "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "license": "MIT", "peer": true, "dependencies": { "crc-32": "^1.2.0", @@ -26732,8 +25911,7 @@ }, "node_modules/serverless/node_modules/decompress-response": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", "peer": true, "dependencies": { "mimic-response": "^3.1.0" @@ -26747,8 +25925,7 @@ }, "node_modules/serverless/node_modules/defer-to-connect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -26756,8 +25933,7 @@ }, "node_modules/serverless/node_modules/get-stream": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", "peer": true, "dependencies": { "pump": "^3.0.0" @@ -26771,8 +25947,7 @@ }, "node_modules/serverless/node_modules/got": { "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", "peer": true, "dependencies": { "@sindresorhus/is": "^4.0.0", @@ -26796,20 +25971,17 @@ }, "node_modules/serverless/node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT", "peer": true }, "node_modules/serverless/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT", "peer": true }, "node_modules/serverless/node_modules/keyv": { "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "license": "MIT", "peer": true, "dependencies": { "json-buffer": "3.0.1" @@ -26817,8 +25989,7 @@ }, "node_modules/serverless/node_modules/lowercase-keys": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -26826,8 +25997,7 @@ }, "node_modules/serverless/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "peer": true, "dependencies": { "yallist": "^4.0.0" @@ -26838,8 +26008,7 @@ }, "node_modules/serverless/node_modules/mimic-response": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -26850,8 +26019,7 @@ }, "node_modules/serverless/node_modules/minipass": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.1.tgz", - "integrity": "sha512-V9esFpNbK0arbN3fm2sxDKqMYgIp7XtVdE4Esj+PE4Qaaxdg1wIw48ITQIOn1sc8xXSmUviVL3cyjMqPlrVkiA==", + "license": "ISC", "peer": true, "engines": { "node": ">=8" @@ -26859,8 +26027,7 @@ }, "node_modules/serverless/node_modules/node-fetch": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "license": "MIT", "peer": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -26879,8 +26046,7 @@ }, "node_modules/serverless/node_modules/normalize-url": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -26891,8 +26057,7 @@ }, "node_modules/serverless/node_modules/p-cancelable": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -26900,8 +26065,7 @@ }, "node_modules/serverless/node_modules/responselike": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", "peer": true, "dependencies": { "lowercase-keys": "^2.0.0" @@ -26912,8 +26076,7 @@ }, "node_modules/serverless/node_modules/semver": { "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "license": "ISC", "peer": true, "dependencies": { "lru-cache": "^6.0.0" @@ -26927,8 +26090,7 @@ }, "node_modules/serverless/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -26942,8 +26104,7 @@ }, "node_modules/serverless/node_modules/tar": { "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "license": "ISC", "peer": true, "dependencies": { "chownr": "^2.0.0", @@ -26959,14 +26120,12 @@ }, "node_modules/serverless/node_modules/tr46": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", "peer": true }, "node_modules/serverless/node_modules/uuid": { "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "license": "MIT", "peer": true, "bin": { "uuid": "dist/bin/uuid" @@ -26974,14 +26133,12 @@ }, "node_modules/serverless/node_modules/webidl-conversions": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", "peer": true }, "node_modules/serverless/node_modules/whatwg-url": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "peer": true, "dependencies": { "tr46": "~0.0.3", @@ -26990,14 +26147,12 @@ }, "node_modules/serverless/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC", "peer": true }, "node_modules/serverless/node_modules/zip-stream": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", - "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -27014,8 +26169,7 @@ }, "node_modules/set-function-length": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -27030,8 +26184,7 @@ }, "node_modules/set-function-name": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -27129,8 +26282,7 @@ }, "node_modules/simple-git": { "version": "3.17.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.17.0.tgz", - "integrity": "sha512-JozI/s8jr3nvLd9yn2jzPVHnhVzt7t7QWfcIoDcqRIGN+f1IINGv52xoZti2kkYfoRhhRvzMSNPfogHMp97rlw==", + "license": "MIT", "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", @@ -27318,8 +26470,7 @@ }, "node_modules/sonic-boom": { "version": "3.5.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.5.0.tgz", - "integrity": "sha512-02A0wEmj4d3aEIW/Sp6LMP1dNcG5cYmQPjhgtytIXa9tNmFZx3ragUPFmyBdgdM0yJJVSWwlLLEVHgrYfA0wtQ==", + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0" } @@ -27337,8 +26488,7 @@ }, "node_modules/sort-keys-length": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", - "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", + "license": "MIT", "peer": true, "dependencies": { "sort-keys": "^1.0.0" @@ -27349,8 +26499,7 @@ }, "node_modules/sort-keys-length/node_modules/sort-keys": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "license": "MIT", "peer": true, "dependencies": { "is-plain-obj": "^1.0.0" @@ -27361,8 +26510,7 @@ }, "node_modules/sorted-array-functions": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", - "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==", + "license": "MIT", "peer": true }, "node_modules/source-list-map": { @@ -27401,9 +26549,8 @@ }, "node_modules/spawk": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/spawk/-/spawk-1.8.1.tgz", - "integrity": "sha512-Ws7F450Kz6u/zxVjNQqZwuiOfs+603qyK3vkeY5Rjgp5wnoK0d/7t5iliXKxDm1Pf/eJr3CcynNA3mAqjIugXA==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.0.0" } @@ -27497,8 +26644,7 @@ }, "node_modules/sprintf-kit": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.1.tgz", - "integrity": "sha512-2PNlcs3j5JflQKcg4wpdqpZ+AjhQJ2OZEo34NXDtlB0tIPG84xaaXhpA8XFacFiwjKA4m49UOYG83y3hbMn/gQ==", + "license": "ISC", "peer": true, "dependencies": { "es5-ext": "^0.10.53" @@ -27529,8 +26675,7 @@ }, "node_modules/ssri": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", "dependencies": { "minipass": "^3.1.1" }, @@ -27724,8 +26869,7 @@ }, "node_modules/stream-promise": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/stream-promise/-/stream-promise-3.2.0.tgz", - "integrity": "sha512-P+7muTGs2C8yRcgJw/PPt61q7O517tDHiwYEzMWo1GSBCcZedUMT/clz7vUNsSxFphIlJ6QUL4GexQKlfJoVtA==", + "license": "ISC", "peer": true, "dependencies": { "2-thenable": "^1.0.0", @@ -27735,8 +26879,7 @@ }, "node_modules/stream-promise/node_modules/is-stream": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -27780,7 +26923,8 @@ }, "node_modules/string-length": { "version": "4.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -27803,8 +26947,7 @@ }, "node_modules/string.prototype.trim": { "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -27820,8 +26963,7 @@ }, "node_modules/string.prototype.trimend": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -27833,8 +26975,7 @@ }, "node_modules/string.prototype.trimstart": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -27885,8 +27026,7 @@ }, "node_modules/strip-dirs": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", - "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "license": "MIT", "peer": true, "dependencies": { "is-natural-number": "^4.0.1" @@ -27922,8 +27062,7 @@ }, "node_modules/strip-outer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "license": "MIT", "peer": true, "dependencies": { "escape-string-regexp": "^1.0.2" @@ -27934,8 +27073,7 @@ }, "node_modules/strip-outer/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.8.0" @@ -27943,8 +27081,7 @@ }, "node_modules/strnum": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + "license": "MIT" }, "node_modules/strong-cluster-control": { "version": "2.2.4", @@ -27986,8 +27123,7 @@ }, "node_modules/strtok3": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", - "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "license": "MIT", "peer": true, "dependencies": { "@tokenizer/token": "^0.3.0", @@ -28063,8 +27199,7 @@ }, "node_modules/tar": { "version": "4.4.19", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", - "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "license": "ISC", "dependencies": { "chownr": "^1.1.4", "fs-minipass": "^1.2.7", @@ -28080,8 +27215,7 @@ }, "node_modules/tar-fs": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "license": "MIT", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -28091,8 +27225,7 @@ }, "node_modules/tar-fs/node_modules/chownr": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "license": "ISC" }, "node_modules/tar-stream": { "version": "2.2.0", @@ -28110,21 +27243,18 @@ }, "node_modules/tar/node_modules/chownr": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "license": "ISC" }, "node_modules/tar/node_modules/fs-minipass": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "license": "ISC", "dependencies": { "minipass": "^2.6.0" } }, "node_modules/tar/node_modules/minipass": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "license": "ISC", "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -28132,16 +27262,14 @@ }, "node_modules/tar/node_modules/minizlib": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "license": "MIT", "dependencies": { "minipass": "^2.9.0" } }, "node_modules/tar/node_modules/mkdirp": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -28151,8 +27279,6 @@ }, "node_modules/tar/node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -28166,12 +27292,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/tar/node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "license": "ISC" }, "node_modules/tcp-port-used": { "version": "1.0.2", @@ -28198,9 +27324,8 @@ }, "node_modules/temp": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, + "license": "MIT", "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -28211,9 +27336,8 @@ }, "node_modules/temp/node_modules/mkdirp": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -28223,9 +27347,8 @@ }, "node_modules/temp/node_modules/rimraf": { "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -28235,8 +27358,7 @@ }, "node_modules/terser": { "version": "4.8.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", - "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "license": "BSD-2-Clause", "dependencies": { "commander": "^2.20.0", "source-map": "~0.6.1", @@ -28372,16 +27494,14 @@ }, "node_modules/thenify": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", "dependencies": { "any-promise": "^1.0.0" } }, "node_modules/thenify-all": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -28391,8 +27511,7 @@ }, "node_modules/thread-stream": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", - "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", + "license": "MIT", "dependencies": { "real-require": "^0.2.0" } @@ -28421,8 +27540,7 @@ }, "node_modules/timers-ext": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "license": "ISC", "peer": true, "dependencies": { "es5-ext": "~0.10.46", @@ -28449,8 +27567,7 @@ }, "node_modules/to-buffer": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "license": "MIT", "peer": true }, "node_modules/to-fast-properties": { @@ -28594,8 +27711,7 @@ }, "node_modules/token-types": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", - "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "license": "MIT", "peer": true, "dependencies": { "@tokenizer/token": "^0.3.0", @@ -28633,8 +27749,7 @@ }, "node_modules/traverse": { "version": "0.6.7", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", - "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", + "license": "MIT", "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -28650,8 +27765,7 @@ }, "node_modules/trim-repeated": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "license": "MIT", "peer": true, "dependencies": { "escape-string-regexp": "^1.0.2" @@ -28662,8 +27776,7 @@ }, "node_modules/trim-repeated/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.8.0" @@ -28675,8 +27788,7 @@ }, "node_modules/tryer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", - "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + "license": "MIT" }, "node_modules/ts-jest": { "version": "29.1.2", @@ -28840,9 +27952,8 @@ }, "node_modules/tsconfig-paths/node_modules/json5": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -28864,9 +27975,8 @@ }, "node_modules/tsutils": { "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -28897,8 +28007,7 @@ }, "node_modules/type": { "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "license": "ISC", "peer": true }, "node_modules/type-check": { @@ -28921,8 +28030,7 @@ }, "node_modules/type-fest": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.0.tgz", - "integrity": "sha512-RqTRtKTzvPpNdDUp1dVkKQRunlPITk4mXeqFlAZoJsS+fLRn8AdPK0TcQDumGayhU7fjlBfiBjsq3pe3rIfXZQ==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=14.16" }, @@ -28932,8 +28040,7 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -28945,8 +28052,7 @@ }, "node_modules/typed-array-byte-length": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -28963,8 +28069,7 @@ }, "node_modules/typed-array-byte-offset": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -28982,8 +28087,7 @@ }, "node_modules/typed-array-length": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -29051,8 +28155,7 @@ }, "node_modules/unbzip2-stream": { "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "license": "MIT", "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -29060,8 +28163,6 @@ }, "node_modules/unbzip2-stream/node_modules/buffer": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -29076,6 +28177,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -29093,8 +28195,7 @@ }, "node_modules/uni-global": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uni-global/-/uni-global-1.0.0.tgz", - "integrity": "sha512-WWM3HP+siTxzIWPNUg7hZ4XO8clKi6NoCAJJWnuRL+BAqyFXF8gC03WNyTefGoUXYc47uYgXxpKLIEvo65PEHw==", + "license": "ISC", "peer": true, "dependencies": { "type": "^2.5.0" @@ -29274,8 +28375,7 @@ }, "node_modules/untildify": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -29463,8 +28563,7 @@ }, "node_modules/velocityjs": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/velocityjs/-/velocityjs-2.0.6.tgz", - "integrity": "sha512-QMYLeYLBX6eqekCin3OPmDAHapaUx3foNFE264ml1/yxRZ8TUUlI1+u6rtN4E8tKNqwzpRPeNgJtjLbgRNK4fw==", + "license": "MIT", "peer": true, "dependencies": { "debug": "^4.3.3" @@ -29900,8 +28999,7 @@ }, "node_modules/wcwidth": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "license": "MIT", "peer": true, "dependencies": { "defaults": "^1.0.3" @@ -29909,8 +29007,7 @@ }, "node_modules/web-streams-polyfill": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "license": "MIT", "peer": true, "engines": { "node": ">= 8" @@ -30297,8 +29394,7 @@ }, "node_modules/which-typed-array": { "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -30335,11 +29431,10 @@ "license": "MIT" }, "node_modules/winston": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", - "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==", + "version": "3.13.0", + "license": "MIT", "dependencies": { - "@colors/colors": "1.5.0", + "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", @@ -30349,14 +29444,14 @@ "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.5.0" + "winston-transport": "^4.7.0" }, "engines": { "node": ">= 12.0.0" } }, "node_modules/winston-transport": { - "version": "4.5.0", + "version": "4.7.0", "license": "MIT", "dependencies": { "logform": "^2.3.2", @@ -30364,7 +29459,14 @@ "triple-beam": "^1.3.0" }, "engines": { - "node": ">= 6.4.0" + "node": ">= 12.0.0" + } + }, + "node_modules/winston/node_modules/@colors/colors": { + "version": "1.6.0", + "license": "MIT", + "engines": { + "node": ">=0.1.90" } }, "node_modules/word-wrap": { @@ -30517,8 +29619,7 @@ }, "node_modules/xml2js": { "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "license": "MIT", "peer": true, "dependencies": { "sax": ">=0.6.0", @@ -30527,8 +29628,7 @@ }, "node_modules/xmlbuilder": { "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=4.0" @@ -30563,22 +29663,19 @@ }, "node_modules/yaml": { "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", "engines": { "node": ">= 6" } }, "node_modules/yaml-ast-parser": { "version": "0.0.43", - "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", - "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "license": "Apache-2.0", "peer": true }, "node_modules/yamljs": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", - "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "license": "MIT", "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -30591,8 +29688,7 @@ }, "node_modules/yamljs/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", "peer": true, "dependencies": { "sprintf-js": "~1.0.2" @@ -30712,12 +29808,44 @@ }, "node_modules/zod": { "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zod2md": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@commander-js/extra-typings": "^12.0.0", + "bundle-require": "^4.0.2", + "commander": "^12.0.0", + "esbuild": "^0.19.11" + }, + "bin": { + "zod2md": "dist/bin.js" + }, + "peerDependencies": { + "zod": "^3.22.0" + } + }, + "node_modules/zod2md/node_modules/@commander-js/extra-typings": { + "version": "12.0.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "commander": "~12.0.0" + } + }, + "node_modules/zod2md/node_modules/commander": { + "version": "12.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "plugins/babel": { "name": "@dotcom-tool-kit/babel", "version": "3.2.0", @@ -30746,8 +29874,7 @@ }, "plugins/babel/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/backend-app": { "name": "@dotcom-tool-kit/backend-app", @@ -30857,8 +29984,7 @@ }, "plugins/circleci-deploy/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/circleci-heroku": { "name": "@dotcom-tool-kit/circleci-heroku", @@ -30879,8 +30005,7 @@ }, "plugins/circleci-heroku/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/circleci-npm": { "name": "@dotcom-tool-kit/circleci-npm", @@ -30901,13 +30026,11 @@ }, "plugins/circleci-npm/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/circleci/node_modules/@jest/schemas": { "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "license": "MIT", "dependencies": { "@sinclair/typebox": "^0.25.16" }, @@ -30917,13 +30040,11 @@ }, "plugins/circleci/node_modules/@sinclair/typebox": { "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + "license": "MIT" }, "plugins/circleci/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -30933,16 +30054,14 @@ }, "plugins/circleci/node_modules/diff-sequences": { "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "plugins/circleci/node_modules/jest-diff": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", @@ -30955,16 +30074,14 @@ }, "plugins/circleci/node_modules/jest-get-type": { "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "license": "MIT", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "plugins/circleci/node_modules/pretty-format": { "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "license": "MIT", "dependencies": { "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", @@ -30976,18 +30093,15 @@ }, "plugins/circleci/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "license": "MIT" }, "plugins/circleci/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/circleci/node_modules/type-fest": { "version": "3.5.4", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.5.4.tgz", - "integrity": "sha512-/Je22Er4LPoln256pcLzj73MUmPrTWg8u4WB1RlxaDl0idJOfD1r259VtKOinp4xLJqJ9zYVMuWOun6Ssp7boA==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=14.16" }, @@ -30997,8 +30111,7 @@ }, "plugins/circleci/node_modules/yaml": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", - "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", + "license": "ISC", "engines": { "node": ">= 14" } @@ -31248,8 +30361,7 @@ }, "plugins/eslint/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/eslint/node_modules/which": { "version": "2.0.2", @@ -31319,8 +30431,7 @@ }, "plugins/heroku/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/husky-npm": { "name": "@dotcom-tool-kit/husky-npm", @@ -31341,8 +30452,7 @@ }, "plugins/husky-npm/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/jest": { "name": "@dotcom-tool-kit/jest", @@ -31368,8 +30478,7 @@ }, "plugins/jest/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/lint-staged": { "name": "@dotcom-tool-kit/lint-staged", @@ -31410,8 +30519,7 @@ }, "plugins/lint-staged-npm/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/lint-staged/node_modules/colorette": { "version": "1.4.0", @@ -31465,8 +30573,7 @@ }, "plugins/lint-staged/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/mocha": { "name": "@dotcom-tool-kit/mocha", @@ -31497,8 +30604,7 @@ }, "plugins/mocha/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/n-test": { "name": "@dotcom-tool-kit/n-test", @@ -31527,9 +30633,8 @@ }, "plugins/n-test/node_modules/@financial-times/n-test": { "version": "6.1.0-beta.1", - "resolved": "https://registry.npmjs.org/@financial-times/n-test/-/n-test-6.1.0-beta.1.tgz", - "integrity": "sha512-xVCswU9R4MWKxtJ+xi9Ur9aZoBiqOvbtDbtD7bEBUMssHdRbs0xXsZNto2fDm18w7TicZZZZfMtbYS8Ob1snag==", "hasInstallScript": true, + "license": "ISC", "dependencies": { "chalk": "^2.3.0", "commander": "^3.0.0", @@ -31550,8 +30655,7 @@ }, "plugins/n-test/node_modules/ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -31561,8 +30665,7 @@ }, "plugins/n-test/node_modules/chalk": { "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -31574,42 +30677,36 @@ }, "plugins/n-test/node_modules/color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "plugins/n-test/node_modules/color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "license": "MIT" }, "plugins/n-test/node_modules/commander": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" + "license": "MIT" }, "plugins/n-test/node_modules/escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", "engines": { "node": ">=0.8.0" } }, "plugins/n-test/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", "engines": { "node": ">=4" } }, "plugins/n-test/node_modules/supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -31619,8 +30716,7 @@ }, "plugins/n-test/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/next-router": { "name": "@dotcom-tool-kit/next-router", @@ -31648,8 +30744,6 @@ }, "plugins/next-router/node_modules/@financial-times/n-flags-client": { "version": "14.0.1", - "resolved": "https://registry.npmjs.org/@financial-times/n-flags-client/-/n-flags-client-14.0.1.tgz", - "integrity": "sha512-gTwqo4Bzu9GQlGgaBF7U9B6cHt4YVPFPSBuyUNbUPB9TJOvdi7wY0TueBFmOOydcfuF1i2HRJeXP6foTfoBoWw==", "dependencies": { "@dotcom-reliability-kit/logger": "^2.2.6", "n-eager-fetch": "^7.0.0", @@ -31662,8 +30756,6 @@ }, "plugins/next-router/node_modules/ft-next-router": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ft-next-router/-/ft-next-router-3.0.0.tgz", - "integrity": "sha512-tQ8c45o2xEhbx/OGuWM/xEL5GkBnKg/mJ2+BVkBayHqvf0vFJCokPVq1Rqw84CQZnIRw/WMYe6j+eD9DEr54uA==", "dependencies": { "@dotcom-reliability-kit/crash-handler": "^3.0.2", "@dotcom-reliability-kit/log-error": "^3.1.0", @@ -31693,9 +30785,8 @@ } }, "plugins/next-router/node_modules/ft-poller": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ft-poller/-/ft-poller-9.0.0.tgz", - "integrity": "sha512-oHo0nICYKdAxsHy66mKBojCddAHfXiR2gcF0hbMoIuDm6tLzXumwUgFcGMQ1EK5R0C2ZVwb20p6kumGP8qLusA==", + "version": "0.0.0", + "license": "MIT", "dependencies": { "@dotcom-reliability-kit/logger": "^2.2.7", "isomorphic-fetch": "^3.0.0", @@ -31708,8 +30799,7 @@ }, "plugins/next-router/node_modules/ft-poller/node_modules/isomorphic-fetch": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "license": "MIT", "dependencies": { "node-fetch": "^2.6.1", "whatwg-fetch": "^3.4.1" @@ -31717,8 +30807,6 @@ }, "plugins/next-router/node_modules/n-eager-fetch": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/n-eager-fetch/-/n-eager-fetch-7.1.0.tgz", - "integrity": "sha512-tPlZDKf1Tzir0czXvu63wuZb5RDIP+Lpqq56dfVu06qJqerAedUp2LspFbKQfxBKZdwpnKf5R9NLLZhEfR5tlQ==", "dependencies": { "isomorphic-fetch": "^3.0.0", "npm-prepublish": "^1.2.2" @@ -31730,8 +30818,7 @@ }, "plugins/next-router/node_modules/n-eager-fetch/node_modules/isomorphic-fetch": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "license": "MIT", "dependencies": { "node-fetch": "^2.6.1", "whatwg-fetch": "^3.4.1" @@ -31739,8 +30826,6 @@ }, "plugins/next-router/node_modules/next-metrics": { "version": "10.0.3", - "resolved": "https://registry.npmjs.org/next-metrics/-/next-metrics-10.0.3.tgz", - "integrity": "sha512-HtYrmL0h79Bho3oW423oQFEW9Piu+i++cgUNM/HUtU2xlWkNtOwhhp3gWz906PexfoB7qaLmE7zS+S8SY32Z3w==", "dependencies": { "@dotcom-reliability-kit/logger": "^2.2.6", "lodash": "^4.17.21", @@ -31753,8 +30838,7 @@ }, "plugins/next-router/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/node": { "name": "@dotcom-tool-kit/node", @@ -31782,8 +30866,7 @@ }, "plugins/node/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/nodemon": { "name": "@dotcom-tool-kit/nodemon", @@ -31812,8 +30895,7 @@ }, "plugins/nodemon/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/npm": { "name": "@dotcom-tool-kit/npm", @@ -31848,8 +30930,7 @@ }, "plugins/npm/node_modules/@npmcli/git": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", - "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", + "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^1.3.2", "lru-cache": "^6.0.0", @@ -31863,9 +30944,8 @@ }, "plugins/npm/node_modules/@types/libnpmpublish": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/libnpmpublish/-/libnpmpublish-4.0.6.tgz", - "integrity": "sha512-xI99EEgpr1R0hpLAKb52QbBYv8ZZa9FDiZS7LEVE6RevjkQHF3BflPR7Mo2F8yxMnqP6eoPkWE0bnWvDC/sA9A==", "dev": true, + "license": "MIT", "dependencies": { "@npm/types": "*", "@types/node-fetch": "*", @@ -31874,9 +30954,8 @@ }, "plugins/npm/node_modules/@types/tar": { "version": "6.1.11", - "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-ThA1WD8aDdVU4VLuyq5NEqriwXErF5gEIJeyT6gHBWU7JtSmW2a5qjNv3/vR82O20mW+1vhmeZJfBQPT3HCugg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "minipass": "^4.0.0" @@ -31884,17 +30963,15 @@ }, "plugins/npm/node_modules/@types/tar/node_modules/minipass": { "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true, + "license": "ISC", "engines": { "node": ">=8" } }, "plugins/npm/node_modules/ignore-walk": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", - "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", + "license": "ISC", "dependencies": { "minimatch": "^3.0.4" }, @@ -31904,8 +30981,7 @@ }, "plugins/npm/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -31915,8 +30991,7 @@ }, "plugins/npm/node_modules/npm-install-checks": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", - "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, @@ -31926,8 +31001,7 @@ }, "plugins/npm/node_modules/npm-packlist": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", - "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", + "license": "ISC", "dependencies": { "glob": "^7.1.6", "ignore-walk": "^4.0.1", @@ -31943,8 +31017,7 @@ }, "plugins/npm/node_modules/npm-pick-manifest": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", - "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", + "license": "ISC", "dependencies": { "npm-install-checks": "^4.0.0", "npm-normalize-package-bin": "^1.0.1", @@ -31954,8 +31027,7 @@ }, "plugins/npm/node_modules/pacote": { "version": "12.0.3", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-12.0.3.tgz", - "integrity": "sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow==", + "license": "ISC", "dependencies": { "@npmcli/git": "^2.1.0", "@npmcli/installed-package-contents": "^1.0.6", @@ -31986,8 +31058,7 @@ }, "plugins/npm/node_modules/pacote/node_modules/tar": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -32002,21 +31073,18 @@ }, "plugins/npm/node_modules/pacote/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", "engines": { "node": ">=8" } }, "plugins/npm/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/npm/node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -32029,8 +31097,7 @@ }, "plugins/npm/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "license": "ISC" }, "plugins/pa11y": { "name": "@dotcom-tool-kit/pa11y", @@ -32054,8 +31121,7 @@ }, "plugins/pa11y/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/package-json-hook": { "name": "@dotcom-tool-kit/package-json-hook", @@ -32086,8 +31152,7 @@ }, "plugins/package-json-hook/node_modules/tslib": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "license": "0BSD" }, "plugins/prettier": { "name": "@dotcom-tool-kit/prettier", @@ -32117,33 +31182,12 @@ }, "plugins/prettier/node_modules/@types/prettier": { "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true + "dev": true, + "license": "MIT" }, "plugins/prettier/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, - "plugins/secret-squirrel": { - "name": "@dotcom-tool-kit/secret-squirrel", - "version": "2.1.4", - "extraneous": true, - "license": "ISC", - "dependencies": { - "@dotcom-tool-kit/logger": "^3.2.0", - "@dotcom-tool-kit/types": "^3.4.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": "16.x || 18.x", - "npm": "7.x || 8.x || 9.x" - }, - "peerDependencies": { - "@financial-times/secret-squirrel": "2.x", - "dotcom-tool-kit": "3.x" - } + "license": "0BSD" }, "plugins/serverless": { "name": "@dotcom-tool-kit/serverless", @@ -32173,8 +31217,7 @@ }, "plugins/serverless/node_modules/tslib": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "license": "0BSD" }, "plugins/typescript": { "name": "@dotcom-tool-kit/typescript", @@ -32201,9 +31244,8 @@ }, "plugins/typescript/node_modules/@babel/code-frame": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -32213,9 +31255,8 @@ }, "plugins/typescript/node_modules/@jest/environment": { "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", - "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", "dev": true, + "license": "MIT", "dependencies": { "@jest/fake-timers": "^29.3.1", "@jest/types": "^29.3.1", @@ -32228,9 +31269,8 @@ }, "plugins/typescript/node_modules/@jest/fake-timers": { "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", - "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.3.1", "@sinonjs/fake-timers": "^9.1.2", @@ -32245,9 +31285,8 @@ }, "plugins/typescript/node_modules/@jest/globals": { "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", - "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", "dev": true, + "license": "MIT", "dependencies": { "@jest/environment": "^29.3.1", "@jest/expect": "^29.3.1", @@ -32260,9 +31299,8 @@ }, "plugins/typescript/node_modules/@jest/types": { "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", - "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", @@ -32277,27 +31315,24 @@ }, "plugins/typescript/node_modules/@sinonjs/fake-timers": { "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.7.0" } }, "plugins/typescript/node_modules/@types/yargs": { "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.17.tgz", - "integrity": "sha512-72bWxFKTK6uwWJAVT+3rF6Jo6RTojiJ27FQo8Rf60AL+VZbzoVPnMFhKsUnbjR8A3BTCYQ7Mv3hnl8T0A+CX9g==", "dev": true, + "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "plugins/typescript/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -32307,18 +31342,16 @@ }, "plugins/typescript/node_modules/ci-info": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", - "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "plugins/typescript/node_modules/jest-message-util": { "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", - "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.3.1", @@ -32336,9 +31369,8 @@ }, "plugins/typescript/node_modules/jest-mock": { "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", - "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.3.1", "@types/node": "*", @@ -32350,9 +31382,8 @@ }, "plugins/typescript/node_modules/jest-util": { "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", - "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", "dev": true, + "license": "MIT", "dependencies": { "@jest/types": "^29.3.1", "@types/node": "*", @@ -32367,9 +31398,8 @@ }, "plugins/typescript/node_modules/pretty-format": { "version": "29.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", - "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, + "license": "MIT", "dependencies": { "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", @@ -32381,9 +31411,8 @@ }, "plugins/typescript/node_modules/react-is": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "dev": true, + "license": "MIT" }, "plugins/typescript/node_modules/typescript": { "version": "4.9.5", @@ -32430,8 +31459,7 @@ }, "plugins/upload-assets-to-s3/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "plugins/webpack": { "name": "@dotcom-tool-kit/webpack", @@ -32531,8 +31559,7 @@ }, "plugins/webpack/node_modules/tslib": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "license": "0BSD" }, "types/financial-times__package-json": { "name": "@types/financial-times__package-json", diff --git a/package.json b/package.json index 2ad23ef14..248c822c9 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "author": "FT.com Platforms Team ", "license": "ISC", "devDependencies": { + "@apaleslimghost/zod2md": "^0.2.0-0", "@commitlint/cli": "^16.1.0", "@commitlint/config-conventional": "^16.0.0", "@dotcom-reliability-kit/eslint-config": "^2.0.0", @@ -39,7 +40,8 @@ "prettier": "^2.8.8", "release-please": "^15.0.0", "ts-jest": "^29.1.2", - "typescript": "~5.4.5" + "typescript": "~5.4.5", + "zod2md": "^0.1.2" }, "workspaces": [ "core/*", diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js new file mode 100644 index 000000000..072864a37 --- /dev/null +++ b/scripts/generate-docs.js @@ -0,0 +1,13 @@ +const { TaskSchemas } = require('../lib/schemas/lib/tasks') +const { HookSchemas } = require('../lib/schemas/lib/hooks') +const { PluginSchemas } = require('../lib/schemas/lib/plugins') + +const { convertSchemas, formatModelsAsMarkdown } = require('zod2md') + +const converted = convertSchemas([{ name: 'Babel', schema: TaskSchemas.Babel }]) + +console.log( + formatModelsAsMarkdown(converted, { + title: 'Options' + }) +) From d19bfe77d38674671eccd4995b9fa0e90fe0b541 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 13:00:41 +0100 Subject: [PATCH 213/321] build: load a plugin's toolkitrc for list of hooks & tasks --- package-lock.json | 2 ++ package.json | 2 ++ scripts/generate-docs.js | 63 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5b512d28b..8471dffe3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "check-engines": "^1.5.0", + "endent": "^2.1.0", "eslint": "^8.37.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-import": "^2.27.5", @@ -40,6 +41,7 @@ "release-please": "^15.0.0", "ts-jest": "^29.1.2", "typescript": "~5.4.5", + "winston": "^3.13.0", "zod2md": "^0.1.2" }, "engines": { diff --git a/package.json b/package.json index 248c822c9..4a5837dbd 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "check-engines": "^1.5.0", + "endent": "^2.1.0", "eslint": "^8.37.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-import": "^2.27.5", @@ -41,6 +42,7 @@ "release-please": "^15.0.0", "ts-jest": "^29.1.2", "typescript": "~5.4.5", + "winston": "^3.13.0", "zod2md": "^0.1.2" }, "workspaces": [ diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index 072864a37..8de448889 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -1,13 +1,64 @@ +const { loadToolKitRC } = require('../core/cli/lib/rc-file') const { TaskSchemas } = require('../lib/schemas/lib/tasks') const { HookSchemas } = require('../lib/schemas/lib/hooks') const { PluginSchemas } = require('../lib/schemas/lib/plugins') +const { default: $t } = require('endent') +const logger = require('winston') const { convertSchemas, formatModelsAsMarkdown } = require('zod2md') +const path = require('path') -const converted = convertSchemas([{ name: 'Babel', schema: TaskSchemas.Babel }]) +function formatSchemas(title, schemas) { + const converted = convertSchemas(schemas) + return formatModelsAsMarkdown(converted, { title }) +} -console.log( - formatModelsAsMarkdown(converted, { - title: 'Options' - }) -) +function formatPluginSchemas({ plugin, hooks, tasks }) { + const tasksWithSchemas = tasks.filter((task) => TaskSchemas[task]) + const hooksWithSchemas = hooks.filter((hook) => HookSchemas[hook]) + return $t` + ${ + PluginSchemas[plugin] + ? formatSchemas(plugin, [ + { + name: ' ', + schema: PluginSchemas[plugin] + } + ]) + : '' + } + ${ + tasksWithSchemas.length + ? formatSchemas( + 'Tasks', + tasksWithSchemas.map((task) => ({ + name: task, + schema: TaskSchemas[task] + })) + ) + : '' + } + ${ + hooksWithSchemas.length + ? formatSchemas( + 'Hooks', + hooksWithSchemas.map((hook) => ({ + name: hook, + schema: HookSchemas[hook] + })) + ) + : '' + } + ` +} + +async function getPluginSchemas(plugin) { + const rcFile = await loadToolKitRC(logger, path.join('plugins', plugin), false) + return { + plugin: `@dotcom-tool-kit/${plugin}`, + hooks: Object.keys(rcFile.installs), + tasks: Object.keys(rcFile.tasks) + } +} + +getPluginSchemas('heroku').then(formatPluginSchemas).then(console.log, console.error) From 419f973060c09f99660c615e899d784594764aae Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 15:38:04 +0100 Subject: [PATCH 214/321] build: replace content between predefined comments in readmes --- scripts/generate-docs.js | 48 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index 8de448889..31e7f75ff 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -4,9 +4,9 @@ const { HookSchemas } = require('../lib/schemas/lib/hooks') const { PluginSchemas } = require('../lib/schemas/lib/plugins') const { default: $t } = require('endent') const logger = require('winston') - -const { convertSchemas, formatModelsAsMarkdown } = require('zod2md') const path = require('path') +const fs = require('fs/promises') +const { convertSchemas, formatModelsAsMarkdown } = require('zod2md') function formatSchemas(title, schemas) { const converted = convertSchemas(schemas) @@ -52,6 +52,10 @@ function formatPluginSchemas({ plugin, hooks, tasks }) { ` } +function postProcessMarkdown(markdown) { + return '## Options\n\n' + markdown.replaceAll(/^#/gm, '###') +} + async function getPluginSchemas(plugin) { const rcFile = await loadToolKitRC(logger, path.join('plugins', plugin), false) return { @@ -61,4 +65,42 @@ async function getPluginSchemas(plugin) { } } -getPluginSchemas('heroku').then(formatPluginSchemas).then(console.log, console.error) +const BEGIN_COMMENT = '\n' +const END_COMMENT = '' + +function replaceBetween(text, replaceWith, startMarker, endMarker) { + const startIndex = text.indexOf(startMarker) + if (startIndex === -1) { + throw new Error(`Start marker "${startMarker}" not found`) + } + + const endIndex = text.indexOf(endMarker, startIndex + startMarker.length) + if (endIndex === -1) { + throw new Error(`End marker "${endMarker}" not found after start marker "${startMarker}"`) + } + + return text.slice(0, startIndex + startMarker.length) + replaceWith + text.slice(endIndex) +} + +async function main() { + const plugins = ['jest'] //await fs.readdir('plugins') + + return await Promise.all( + plugins.map(async (plugin) => { + const readmePath = path.join('plugins', plugin, 'readme.md') + const schemas = await getPluginSchemas(plugin) + const generatedOptionsMarkdown = postProcessMarkdown(formatPluginSchemas(schemas)) + + const originalReadme = await fs.readFile(readmePath, 'utf-8') + const replacedReadme = replaceBetween( + originalReadme, + generatedOptionsMarkdown, + BEGIN_COMMENT, + END_COMMENT + ) + await fs.writeFile(readmePath, replacedReadme, 'utf-8') + }) + ) +} + +main().then(console.log, console.error) From 5b3c37978edc8ba8c585f80b0f279c6e384e4f94 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 15:54:31 +0100 Subject: [PATCH 215/321] build: improve generated markdown formatting --- scripts/generate-docs.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index 31e7f75ff..bb8231deb 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -10,7 +10,7 @@ const { convertSchemas, formatModelsAsMarkdown } = require('zod2md') function formatSchemas(title, schemas) { const converted = convertSchemas(schemas) - return formatModelsAsMarkdown(converted, { title }) + return formatModelsAsMarkdown(converted, { title, transformName: (name) => '`' + name + '`' }) } function formatPluginSchemas({ plugin, hooks, tasks }) { @@ -19,9 +19,9 @@ function formatPluginSchemas({ plugin, hooks, tasks }) { return $t` ${ PluginSchemas[plugin] - ? formatSchemas(plugin, [ + ? formatSchemas('Plugin-wide options', [ { - name: ' ', + name: plugin, schema: PluginSchemas[plugin] } ]) @@ -30,7 +30,7 @@ function formatPluginSchemas({ plugin, hooks, tasks }) { ${ tasksWithSchemas.length ? formatSchemas( - 'Tasks', + 'Task options', tasksWithSchemas.map((task) => ({ name: task, schema: TaskSchemas[task] @@ -41,7 +41,7 @@ function formatPluginSchemas({ plugin, hooks, tasks }) { ${ hooksWithSchemas.length ? formatSchemas( - 'Hooks', + 'Hook options', hooksWithSchemas.map((hook) => ({ name: hook, schema: HookSchemas[hook] @@ -53,7 +53,7 @@ function formatPluginSchemas({ plugin, hooks, tasks }) { } function postProcessMarkdown(markdown) { - return '## Options\n\n' + markdown.replaceAll(/^#/gm, '###') + return markdown.replace(/^#/gm, '##').replace(/_Object containing the following properties:_\n\n/g, '') } async function getPluginSchemas(plugin) { @@ -83,7 +83,7 @@ function replaceBetween(text, replaceWith, startMarker, endMarker) { } async function main() { - const plugins = ['jest'] //await fs.readdir('plugins') + const plugins = ['serverless'] //await fs.readdir('plugins') return await Promise.all( plugins.map(async (plugin) => { From cf675b65bed668e121f76769524e7b1ddc5ffbf9 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 16:16:01 +0100 Subject: [PATCH 216/321] docs(serverless): add descriptions for serverless schemas --- lib/schemas/src/plugins/serverless.ts | 20 ++++++++--- lib/schemas/src/tasks/serverless-run.ts | 17 +++++++--- plugins/serverless/readme.md | 45 +++++++++++++++---------- 3 files changed, 56 insertions(+), 26 deletions(-) diff --git a/lib/schemas/src/plugins/serverless.ts b/lib/schemas/src/plugins/serverless.ts index f84ee7322..4861c3dda 100644 --- a/lib/schemas/src/plugins/serverless.ts +++ b/lib/schemas/src/plugins/serverless.ts @@ -2,10 +2,22 @@ import { PromptGenerators } from '../prompts' import { z } from 'zod' export const ServerlessSchema = z.object({ - awsAccountId: z.string(), - systemCode: z.string(), - regions: z.array(z.string()).default(['eu-west-1']), - configPath: z.string().optional() + awsAccountId: z + .string() + .describe( + 'the ID of the AWS account you wish to deploy to (account IDs can be found at the [FT login page](https://awslogin.in.ft.com/))' + ), + systemCode: z.string().describe('the system code for your app'), + regions: z + .array(z.string()) + .default(['eu-west-1']) + .describe('an array of AWS regions you want to deploy to'), + configPath: z + .string() + .optional() + .describe( + 'path to your serverless config file. If this is not provided, Serverless defaults to `./serverless.yml` but [other config fomats are accepted](https://www.serverless.com/framework/docs/providers/aws/guide/intro#alternative-configuration-format)' + ) }) export type ServerlessOptions = z.infer diff --git a/lib/schemas/src/tasks/serverless-run.ts b/lib/schemas/src/tasks/serverless-run.ts index 8c5892d24..965fead31 100644 --- a/lib/schemas/src/tasks/serverless-run.ts +++ b/lib/schemas/src/tasks/serverless-run.ts @@ -1,9 +1,18 @@ import { z } from 'zod' -export const ServerlessRunSchema = z.object({ - ports: z.number().array().default([3001, 3002, 3003]), - useDoppler: z.boolean().default(true) -}) +export const ServerlessRunSchema = z + .object({ + ports: z + .number() + .array() + .default([3001, 3002, 3003]) + .describe('ports to try to bind to for this application'), + useDoppler: z + .boolean() + .default(true) + .describe('run the application with environment variables from Doppler') + }) + .describe('Run serverless functions locally') export type ServerlessRunOptions = z.infer diff --git a/plugins/serverless/readme.md b/plugins/serverless/readme.md index 7456ed5f9..ff61dcca3 100644 --- a/plugins/serverless/readme.md +++ b/plugins/serverless/readme.md @@ -19,23 +19,32 @@ plugins: - '@dotcom-tool-kit/serverless' ``` -## Options - -| Key | Description | Default value | -|-|-|-| -| `awsAccountId` | [required] the ID of the AWS account you wish to deploy to (account IDs can be found at the [FT login page](https://awslogin.in.ft.com/)) | none | -| `systemCode` | [required] the system code for your app | none | -| `regions` | [optional] an array of AWS regions you want to deploy to | `['eu-west-1']` | -| `configPath` | [optional] path to your serverless config file. If this is not provided aws defaults to `./serverless.yml` but [other config fomats are accepted](https://www.serverless.com/framework/docs/providers/aws/guide/intro#alternative-configuration-format)| | -| `useVault` | option to run the application with environment variables from Vault | `true` | -| `ports` | ports to try to bind to for this application | `[3001, 3002, 3003]` | -| `buildNumVariable` | an environment variable used to get a unique ID to use in the provisioning stage | `CIRCLE_BUILD_NUM` | - + ## Tasks -| Task | Description | Default hooks | -|-|-|-| -| `ServerlessRun` | Run application with `serverless` | `run:local` | -| `ServerlessProvision` | Deploy review app with `serverless` | `deploy:review` | -| `ServerlessTeardown` | Remove review app with `serverless` | `teardown:review` | -| `ServerlessDeploy` | Deploy production app with `serverless` | `deploy:production` | +### `ServerlessRun` + +Run serverless functions locally +#### Options + +| Property | Description | Type | Default | +| :----------- | :---------------------------------------------------------- | :-------------- | :----------------- | +| `ports` | ports to try to bind to for this application | `Array` | `[3001,3002,3003]` | +| `useDoppler` | run the application with environment variables from Doppler | `boolean` | `true` | + +_All properties are optional._ + + +## Plugin-wide options + +### `@dotcom-tool-kit/serverless` + +| Property | Description | Type | Default | +| :---------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------- | :-------------- | +| **`awsAccountId`** (\*) | the ID of the AWS account you wish to deploy to (account IDs can be found at the [FT login page](https://awslogin.in.ft.com/)) | `string` | | +| **`systemCode`** (\*) | the system code for your app | `string` | | +| `regions` | an array of AWS regions you want to deploy to | `Array` | `["eu-west-1"]` | +| `configPath` | path to your serverless config file. If this is not provided, Serverless defaults to `./serverless.yml` but [other config fomats are accepted](https://www.serverless.com/framework/docs/providers/aws/guide/intro#alternative-configuration-format) | `string` | | + +_(\*) Required._ + From 396d79fe03da8e1ddc58fc1fdb5f1aedd884ffc3 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 16:16:35 +0100 Subject: [PATCH 217/321] build: use the autogenerated output for toplevel hooks and tasks headers --- scripts/generate-docs.js | 54 +++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index bb8231deb..2c80860df 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -10,30 +10,27 @@ const { convertSchemas, formatModelsAsMarkdown } = require('zod2md') function formatSchemas(title, schemas) { const converted = convertSchemas(schemas) - return formatModelsAsMarkdown(converted, { title, transformName: (name) => '`' + name + '`' }) + return postProcessMarkdown( + formatModelsAsMarkdown(converted, { title, transformName: (name) => '`' + name + '`' }) + ) } -function formatPluginSchemas({ plugin, hooks, tasks }) { +async function formatPluginSchemas(plugin) { + const rcFile = await loadToolKitRC(logger, path.join('plugins', plugin), false) + const pluginPackage = `@dotcom-tool-kit/${plugin}` + const hooks = Object.keys(rcFile.installs) + const tasks = Object.keys(rcFile.tasks) + const tasksWithSchemas = tasks.filter((task) => TaskSchemas[task]) const hooksWithSchemas = hooks.filter((hook) => HookSchemas[hook]) return $t` - ${ - PluginSchemas[plugin] - ? formatSchemas('Plugin-wide options', [ - { - name: plugin, - schema: PluginSchemas[plugin] - } - ]) - : '' - } ${ tasksWithSchemas.length ? formatSchemas( - 'Task options', + 'Tasks', tasksWithSchemas.map((task) => ({ name: task, - schema: TaskSchemas[task] + schema: TaskSchemas[task].describe((TaskSchemas[task].description ?? '') + '\n### Task options') })) ) : '' @@ -41,13 +38,23 @@ function formatPluginSchemas({ plugin, hooks, tasks }) { ${ hooksWithSchemas.length ? formatSchemas( - 'Hook options', + 'Hooks', hooksWithSchemas.map((hook) => ({ name: hook, - schema: HookSchemas[hook] + schema: HookSchemas[hook].describe((HookSchemas[hook].description ?? '') + '\n### Hook options') })) ) : '' + } + ${ + PluginSchemas[pluginPackage] + ? formatSchemas('Plugin-wide options', [ + { + name: pluginPackage, + schema: PluginSchemas[pluginPackage] + } + ]) + : '' } ` } @@ -56,15 +63,6 @@ function postProcessMarkdown(markdown) { return markdown.replace(/^#/gm, '##').replace(/_Object containing the following properties:_\n\n/g, '') } -async function getPluginSchemas(plugin) { - const rcFile = await loadToolKitRC(logger, path.join('plugins', plugin), false) - return { - plugin: `@dotcom-tool-kit/${plugin}`, - hooks: Object.keys(rcFile.installs), - tasks: Object.keys(rcFile.tasks) - } -} - const BEGIN_COMMENT = '\n' const END_COMMENT = '' @@ -83,13 +81,12 @@ function replaceBetween(text, replaceWith, startMarker, endMarker) { } async function main() { - const plugins = ['serverless'] //await fs.readdir('plugins') + const plugins = ['circleci'] //await fs.readdir('plugins') return await Promise.all( plugins.map(async (plugin) => { const readmePath = path.join('plugins', plugin, 'readme.md') - const schemas = await getPluginSchemas(plugin) - const generatedOptionsMarkdown = postProcessMarkdown(formatPluginSchemas(schemas)) + const generatedOptionsMarkdown = await formatPluginSchemas(plugin) const originalReadme = await fs.readFile(readmePath, 'utf-8') const replacedReadme = replaceBetween( @@ -98,6 +95,7 @@ async function main() { BEGIN_COMMENT, END_COMMENT ) + await fs.writeFile(readmePath, replacedReadme, 'utf-8') }) ) From 49c69d8c106caf309091aa1097ae5f7e9fbc71c3 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 16:27:03 +0100 Subject: [PATCH 218/321] build: run generate-docs on all plugins --- scripts/generate-docs.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index 2c80860df..5ddd41eb8 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -81,7 +81,7 @@ function replaceBetween(text, replaceWith, startMarker, endMarker) { } async function main() { - const plugins = ['circleci'] //await fs.readdir('plugins') + const plugins = await fs.readdir('plugins') return await Promise.all( plugins.map(async (plugin) => { @@ -89,14 +89,20 @@ async function main() { const generatedOptionsMarkdown = await formatPluginSchemas(plugin) const originalReadme = await fs.readFile(readmePath, 'utf-8') - const replacedReadme = replaceBetween( - originalReadme, - generatedOptionsMarkdown, - BEGIN_COMMENT, - END_COMMENT - ) - await fs.writeFile(readmePath, replacedReadme, 'utf-8') + try { + const replacedReadme = replaceBetween( + originalReadme, + generatedOptionsMarkdown, + BEGIN_COMMENT, + END_COMMENT + ) + + await fs.writeFile(readmePath, replacedReadme, 'utf-8') + console.log(`written ${readmePath}`) + } catch (e) { + console.error(`no replacement markers in ${readmePath}`) + } }) ) } From ebb71e362126237036b1d8ab1cef12aae868084e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 16:27:30 +0100 Subject: [PATCH 219/321] docs(babel): add documentation for babel plugin --- lib/schemas/src/tasks/babel.ts | 19 +++++++++++------ plugins/babel/readme.md | 36 ++++++++++++++++++++++++++++++++ plugins/babel/src/tasks/babel.ts | 4 ++-- plugins/serverless/readme.md | 2 +- 4 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 plugins/babel/readme.md diff --git a/lib/schemas/src/tasks/babel.ts b/lib/schemas/src/tasks/babel.ts index d7bfed739..b0b75d676 100644 --- a/lib/schemas/src/tasks/babel.ts +++ b/lib/schemas/src/tasks/babel.ts @@ -1,11 +1,18 @@ import { z } from 'zod' -export const BabelSchema = z.object({ - files: z.string().optional(), - outputPath: z.string().optional(), - configFile: z.string().optional(), - envName: z.union([z.literal('production'), z.literal('development')]) -}) +export const BabelSchema = z + .object({ + files: z.string().default('src/**/*.js').describe('a glob pattern of files to build in your repo'), + outputPath: z.string().default('lib').describe('folder to output built files into'), + configFile: z + .string() + .optional() + .describe('path to the Babel [config file](https://babeljs.io/docs/configuration) to use'), + envName: z + .union([z.literal('production'), z.literal('development')]) + .describe('the Babel [environment](https://babeljs.io/docs/options#env) to use') + }) + .describe('Compile files with Babel') export type BabelOptions = z.infer diff --git a/plugins/babel/readme.md b/plugins/babel/readme.md new file mode 100644 index 000000000..159183fd3 --- /dev/null +++ b/plugins/babel/readme.md @@ -0,0 +1,36 @@ +# @dotcom-tool-kit/babel + +A plugin to run [Babel](https://babeljs.io/) to compile ES2015+ syntax. + +## Installation + +With Tool Kit [already set up](https://github.com/financial-times/dotcom-tool-kit#installing-and-using-tool-kit), install this plugin as a dev dependency: + +```sh +npm install --save-dev @dotcom-tool-kit/jest +``` + +And add it to your repo's `.toolkitrc.yml`: + +```yaml +plugins: + - '@dotcom-tool-kit/jest' +``` + + +## Tasks + +### `Babel` + +Compile files with Babel +#### Task options + +| Property | Description | Type | Default | +| :----------------- | :---------------------------------------------------------------------------- | :------------------------------ | :-------------- | +| `files` | a glob pattern of files to build in your repo | `string` | `'src/**/*.js'` | +| `outputPath` | folder to output built files into | `string` | `'lib'` | +| `configFile` | path to the Babel [config file](https://babeljs.io/docs/configuration) to use | `string` | | +| **`envName`** (\*) | the Babel [environment](https://babeljs.io/docs/options#env) to use | `'production' \| 'development'` | | + +_(\*) Required._ + diff --git a/plugins/babel/src/tasks/babel.ts b/plugins/babel/src/tasks/babel.ts index 140e83fb8..207eb2065 100644 --- a/plugins/babel/src/tasks/babel.ts +++ b/plugins/babel/src/tasks/babel.ts @@ -13,7 +13,7 @@ export default class Babel extends Task<{ task: typeof BabelSchema }> { static description = 'build babel' async run(): Promise { - const fileGlob = this.options.files ?? 'src/**/*.js' + const fileGlob = this.options.files const files = await fg(fileGlob) // Work out the root of the glob so we can strip this part of the path out of // the outputted files. @@ -21,7 +21,7 @@ export default class Babel extends Task<{ task: typeof BabelSchema }> { // a glob of 'src/a/**/*.js' = src/a/b.js -> lib/b.js const { base } = fg.generateTasks(fileGlob)[0] - const outputPath = this.options.outputPath ?? 'lib' + const outputPath = this.options.outputPath this.logger.info('running babel') const unhook = hookConsole(this.logger, 'babel') diff --git a/plugins/serverless/readme.md b/plugins/serverless/readme.md index ff61dcca3..0d1d53384 100644 --- a/plugins/serverless/readme.md +++ b/plugins/serverless/readme.md @@ -25,7 +25,7 @@ plugins: ### `ServerlessRun` Run serverless functions locally -#### Options +#### Task options | Property | Description | Type | Default | | :----------- | :---------------------------------------------------------- | :-------------- | :----------------- | From 77731ac525368e07155146ca40ffad4a8dba61c3 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 16:39:46 +0100 Subject: [PATCH 220/321] docs(circleci): add descriptions for circleci options --- lib/schemas/src/hooks/circleci.ts | 35 ++++++++++++++++++++---- lib/schemas/src/plugins/circleci.ts | 8 +++++- plugins/circleci/readme.md | 41 +++++++++++++++++++++-------- 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/lib/schemas/src/hooks/circleci.ts b/lib/schemas/src/hooks/circleci.ts index ed84d087e..9dc55f547 100644 --- a/lib/schemas/src/hooks/circleci.ts +++ b/lib/schemas/src/hooks/circleci.ts @@ -32,12 +32,37 @@ export const CircleCiCustomConfig = z.record(z.unknown()) export type CircleCiCustomConfig = z.infer export const CircleCiSchema = z.object({ - executors: z.array(CircleCiExecutor).optional(), - jobs: z.array(CircleCiJob).optional(), - workflows: z.array(CircleCiWorkflow).optional(), - custom: CircleCiCustomConfig.optional(), - disableBaseConfig: z.boolean().optional() + executors: z + .array(CircleCiExecutor) + .optional() + .describe('an array of additional CircleCI executors to output in the generated config.'), + jobs: z + .array(CircleCiJob) + .optional() + .describe( + 'an array of additional CircleCI jobs to output in the generated config. these are used for running Tool Kit commands. for running arbitrary shell commands, use `custom`.' + ), + workflows: z + .array(CircleCiWorkflow) + .optional() + .describe( + 'an array of additional CircleCI workflows to output in the generated config. these reference jobs defined in the `jobs` option.' + ), + custom: CircleCiCustomConfig.optional().describe( + 'arbitrary additional CircleCI configuration that will be merged into the Tool Kit-generated config.' + ), + disableBaseConfig: z + .boolean() + .optional() + .describe( + 'set to `true` to omit the Tool Kit CircleCI boilerplate. should be used along with `custom` to provide your own boilerplate.' + ) }) + .describe(`This hook automatically manages \`.circleci/config.yml\` in your repo to provide configuration for CircleCI workflows to run Tool Kit commands and tasks. + +Options provided in your repository's \`.toolkitrc.yml\` for this hook are merged with any Tool Kit plugin that also provides options for the hook. + +Unless they conflict, your options are appended to options from plugins, allowing you to define custom CircleCI jobs and workflows in your repository that work alongside those from plugins.`) export type CircleCiOptions = z.infer diff --git a/lib/schemas/src/plugins/circleci.ts b/lib/schemas/src/plugins/circleci.ts index f5695a87f..2b572f49f 100644 --- a/lib/schemas/src/plugins/circleci.ts +++ b/lib/schemas/src/plugins/circleci.ts @@ -1,7 +1,13 @@ import { z } from 'zod' export const CircleCISchema = z.object({ - cimgNodeVersions: z.string().array().default(['18.19-browsers']) + cimgNodeVersions: z + .string() + .array() + .default(['18.19-browsers']) + .describe( + 'list of CircleCI [Node.js image versions](https://circleci.com/developer/images/image/cimg/node) to use. if more than one is provided, a [matrix build](https://circleci.com/docs/using-matrix-jobs/) will be generated in your CircleCI config.' + ) }) export type CircleCIOptions = z.infer diff --git a/plugins/circleci/readme.md b/plugins/circleci/readme.md index 7cf470741..4fbdbc45f 100644 --- a/plugins/circleci/readme.md +++ b/plugins/circleci/readme.md @@ -1,6 +1,6 @@ # @dotcom-tool-kit/circleci -This plugin exposes state from the CircleCI environment for other plugins to consume generically. It also manages Tool Kit hooks that are run from CircleCI workflows. +This plugin manages Tool Kit commands that are run from CircleCI workflows, via a Tool Kit [`Hook`](#hooks) that automatically manages `.circleci/config.yml`. It also exposes state from the CircleCI environment for other plugins to consume generically. This plugin will be installed as a dependency of the [frontend-app](https://github.com/Financial-Times/dotcom-tool-kit/tree/main/plugins/frontend-app), [backend-heroku-app](https://github.com/Financial-Times/dotcom-tool-kit/tree/main/plugins/backend-heroku-app), [component](https://github.com/Financial-Times/dotcom-tool-kit/tree/main/plugins/component), [circleci-deploy](https://github.com/Financial-Times/dotcom-tool-kit/tree/main/plugins/circleci-deploy), and [circleci-npm](https://github.com/Financial-Times/dotcom-tool-kit/tree/main/plugins/circleci-npm) plugins so you do not need to install it separately if you are using any of those plugins. @@ -25,16 +25,35 @@ And install this plugin's hooks: npx dotcom-tool-kit --install ``` -## Options + +## Hooks -| Key | Description | Default value | -| ------------- | --------------------------------------- | ------------- | -| `nodeVersion` | The Node versioned docker image tag for CircleCI to use. Any [CircleCI image tag](https://circleci.com/developer/images/image/cimg/node#image-tags) is valid, for example `18.16-browsers` or `16.14`. Can be an array of versions to create a matrix pipeline. The first version in the list is what will be used for publishing etc. | `16.14-browsers` | +### `CircleCi` -## Hooks +This hook automatically manages `.circleci/config.yml` in your repo to provide configuration for CircleCI workflows to run Tool Kit commands and tasks. + +Options provided in your repository's `.toolkitrc.yml` for this hook are merged with any Tool Kit plugin that also provides options for the hook. + +Unless they conflict, your options are appended to options from plugins, allowing you to define custom CircleCI jobs and workflows in your repository that work alongside those from plugins. +#### Hook options + +| Property | Description | Type | +| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `executors` | an array of additional CircleCI executors to output in the generated config. | _Array of objects:_
  • `name`: `string`
  • `image`: `string`
| +| `jobs` | an array of additional CircleCI jobs to output in the generated config. these are used for running Tool Kit commands. for running arbitrary shell commands, use `custom`. | _Array of objects:_
  • `name`: `string`
  • `command`: `string`
| +| `workflows` | an array of additional CircleCI workflows to output in the generated config. these reference jobs defined in the `jobs` option. | _Array of objects:_
  • `name`: `string`
  • `jobs`: _Array of objects:_
    • `name`: `string`
    • `requires`: `Array`
    • `splitIntoMatrix`: `boolean`
    • `custom`: `unknown` (_nullable_)
  • `runOnRelease`: `boolean`
  • `custom`: `unknown` (_nullable_)
| +| `custom` | arbitrary additional CircleCI configuration that will be merged into the Tool Kit-generated config. | _Object with dynamic keys of type_ `string` _and values of type_ `unknown` (_optional & nullable_) | +| `disableBaseConfig` | set to `true` to omit the Tool Kit CircleCI boilerplate. should be used along with `custom` to provide your own boilerplate. | `boolean` | + +_All properties are optional._ + +## Plugin-wide options + +### `@dotcom-tool-kit/circleci` + +| Property | Description | Type | Default | +| :----------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------- | :------------------- | +| `cimgNodeVersions` | list of CircleCI [Node.js image versions](https://circleci.com/developer/images/image/cimg/node) to use. if more than one is provided, a [matrix build](https://circleci.com/docs/using-matrix-jobs/) will be generated in your CircleCI config. | `Array` | `["18.19-browsers"]` | -| Event | Description | Installed to... | Default Hooks | -| ------------- | -------------------------------------------------------- | -------------------------------------- | -------------------------------------- | -| `build:ci` | Compile any assets or code required for your app to run. | `build` job in `.circle/config.yml` | `WebpackProduction`, `BabelProduction` | -| `test:ci` | Run your app's test suite. | `test` job in `.circle/config.yml` | `Eslint`, `Mocha`, `JestCi` | -| `test:review` | Run your app's E2E tests against a deployed Review App. | `e2e-test` job in `.circle/config.yml` | `NTest`, `Pa11y` | +_All properties are optional._ + From 75181c5ee0e8b51926363431d426dc601e7a01ce Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 16:46:20 +0100 Subject: [PATCH 221/321] docs(cypress): add descriptions for cypress options --- lib/schemas/src/tasks/cypress.ts | 14 +++++++--- plugins/cypress/readme.md | 44 +++++++++++++++----------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/lib/schemas/src/tasks/cypress.ts b/lib/schemas/src/tasks/cypress.ts index d13485cf9..2984510ea 100644 --- a/lib/schemas/src/tasks/cypress.ts +++ b/lib/schemas/src/tasks/cypress.ts @@ -1,8 +1,16 @@ import { z } from 'zod' -export const CypressSchema = z.object({ - url: z.string().optional() -}) +export const CypressSchema = z + .object({ + url: z + .string() + .optional() + .describe( + 'URL to run Cypress against. If running in an environment such as a review or staging app build that has Tool Kit state with a URL for an app to run against, that will override this option.' + ) + }) + .describe('Run Cypress end-to-end tests') + export type CypressOptions = z.infer export const Schema = CypressSchema diff --git a/plugins/cypress/readme.md b/plugins/cypress/readme.md index c30bb8407..80979cbee 100644 --- a/plugins/cypress/readme.md +++ b/plugins/cypress/readme.md @@ -19,25 +19,28 @@ plugins: ### Testing with Cypress locally -For local development, by default the `CypressLocal` task runs on the `e2e:local` hook. This hook is also defined within the `cypress` plugin and will install itself into your `package.json` config as the script `e2e-local`. Therefore, to run Cypress on a local instance of your project you just need to call `npm run e2e-local`. Note that, by default, this task does __not__ run your application for you, so if that's controlled by Tool Kit it's recommended you add its task to the `e2e:local` hook too. For example, your config could look like: +> [!IMPORTANT] +> Please check this documentation and make sure it's up to date with the way the Cypress plugin works now. + +For local development, by default the `CypressLocal` task runs on the `e2e:local` command. This command is also defined within the `cypress` plugin and will install itself into your `package.json` config as the script `e2e-local`. Therefore, to run Cypress on a local instance of your project you just need to call `npm run e2e-local`. Note that, by default, this task does __not__ run your application for you, so if that's controlled by Tool Kit it's recommended you add its task to the `e2e:local` command too. For example, your config could look like: ```yml plugins: - '@dotcom-tool-kit/cypress' - '@dotcom-tool-kit/node' -hooks: +command: 'e2e:local': - Node - - CypressLocal + - Cypress ``` ### Testing with Cypress on CI -The `CypressCI` task runs on the `test:review` and `test:staging` hooks by default. These will run your Cypress end-to-end tests against the currently deployed review or staging app respectively. +The `CypressCI` task runs on the `test:review` and `test:staging` commands by default. These will run your Cypress end-to-end tests against the currently deployed review or staging app respectively. -### Running on another hook -You can also configure Cypress to run on any other hook; for example, if you want to run it with `npm run test` via the `npm` plugin, you can manually configure Cypress to run on `npm`'s `test:local` hook: +### Running on another command +You can also configure Cypress to run on any other command; for example, if you want to run it with `npm run test` via the `npm` plugin, you can manually configure Cypress to run on `npm`'s `test:local` command: ```yml plugins: @@ -45,27 +48,22 @@ plugins: - '@dotcom-tool-kit/node' - '@dotcom-tool-kit/npm' -hooks: +command: 'test:local': - Node - - CypressLocal + - Cypress ``` + +## Tasks -## Options - -| Key | Description | Default value | -|-|-|-| -| `localUrl` | URL for Cypress to connect to for local tests | _required (if using `CypressLocal`)_ | - -## Hooks +### `Cypress` -| Event | Description | Installed to...| Default Tasks -|-|-|-|-| -| `e2e:local` | Run end-to-end tests locally | `e2e-local` job in `package.json` | `CypressLocal` | +Run Cypress end-to-end tests +#### Task options -## Tasks +| Property | Description | Type | +| :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | +| `url` | URL to run Cypress against. If running in an environment such as a review or staging app build that has Tool Kit state with a URL for an app to run against, that will override this option. | `string` | -| Task | Description | Default hooks | -|-|-|-| -| `CypressLocal` | Run Cypress against local app | `e2e:local` | -| `CypressCI` | Run Cypress against Heroku apps | `test:review`, `test:staging` | +_All properties are optional._ + From eb2bc78f4d54162f55af63c4fa819ee61051525d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 16:50:45 +0100 Subject: [PATCH 222/321] docs(eslint): add descriptions for eslint options --- lib/schemas/src/tasks/eslint.ts | 22 ++++++++++++++++++---- plugins/eslint/readme.md | 29 ++++++++++++----------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/lib/schemas/src/tasks/eslint.ts b/lib/schemas/src/tasks/eslint.ts index daca70121..4ec1d894c 100644 --- a/lib/schemas/src/tasks/eslint.ts +++ b/lib/schemas/src/tasks/eslint.ts @@ -1,9 +1,23 @@ import { z } from 'zod' -export const ESLintSchema = z.object({ - configPath: z.string().optional(), - files: z.string().array().or(z.string()).default(['**/*.js']) -}) +export const ESLintSchema = z + .object({ + configPath: z + .string() + .optional() + .describe( + 'Path to the [ESLint config file](https://eslint.org/docs/v8.x/use/configure/configuration-files) to use.' + ), + files: z + .string() + .array() + .or(z.string()) + .default(['**/*.js']) + .describe( + 'The glob patterns for lint target files. This can either be a string or an array of strings.' + ) + }) + .describe('Runs `eslint` to lint and format target files.') export type ESLintOptions = z.infer diff --git a/plugins/eslint/readme.md b/plugins/eslint/readme.md index ca76654bd..dfb2993f0 100644 --- a/plugins/eslint/readme.md +++ b/plugins/eslint/readme.md @@ -17,23 +17,18 @@ plugins: - '@dotcom-tool-kit/eslint' ``` -## Options + +## Tasks -| Key | Description | Default value | -|-|-|-| -| `files` | The glob patterns for lint target files. This can either be a string or an array of strings | `'**/*.js'` | -| `options` | The [options](https://eslint.org/docs/latest/developer-guide/nodejs-api#-new-eslintoptions) for the ESLint constructor. This allows for additional flexibility as some of these options, such as `errorOnUnmatchedPattern`, are only applicable at this level but not in your eslintrc.* file | n/a | -| `config` | *Deprecated*. Use `options` instead | n/a | +### `Eslint` -Example: -``` -'@dotcom-tool-kit/eslint': - files: server/*.js' - options: - errorOnUnmatchedPattern: false -``` -## Tasks +Runs `eslint` to lint and format target files. +#### Task options + +| Property | Description | Type | Default | +| :----------- | :------------------------------------------------------------------------------------------------------- | :------------------------ | :------------ | +| `configPath` | Path to the [ESLint config file](https://eslint.org/docs/v8.x/use/configure/configuration-files) to use. | `string` | | +| `files` | The glob patterns for lint target files. This can either be a string or an array of strings. | `Array \| string` | `["**/*.js"]` | -| Task | Description | Preconfigured hooks | -|-|-|-| -| `Eslint` | runs `eslint` to lint and format target files | `test:local`, `test:ci`, `test:staged` | \ No newline at end of file +_All properties are optional._ + From 9b17eb1f31d14bfb1c9ee3435f3ea62e70d349f7 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 16:57:55 +0100 Subject: [PATCH 223/321] docs(jest): move option descriptions to schema --- lib/schemas/src/tasks/jest.ts | 18 ++++++++++++++---- plugins/jest/readme.md | 32 ++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/lib/schemas/src/tasks/jest.ts b/lib/schemas/src/tasks/jest.ts index abbe98379..ed4c9d1d7 100644 --- a/lib/schemas/src/tasks/jest.ts +++ b/lib/schemas/src/tasks/jest.ts @@ -1,9 +1,19 @@ import { z } from 'zod' -export const JestSchema = z.object({ - configPath: z.string().optional(), - ci: z.literal(true).optional() -}) +export const JestSchema = z + .object({ + configPath: z + .string() + .optional() + .describe( + "Path to the [Jest config file](https://jestjs.io/docs/27.x/configuration). Use Jest's own [config resolution](https://jestjs.io/docs/configuration/) by default." + ), + ci: z + .literal(true) + .optional() + .describe('Whether to run Jest in [CI mode](https://jestjs.io/docs/cli#--ci).') + }) + .describe('Runs `jest` to execute tests.') export type JestOptions = z.infer diff --git a/plugins/jest/readme.md b/plugins/jest/readme.md index 796032f75..e4e6391d1 100644 --- a/plugins/jest/readme.md +++ b/plugins/jest/readme.md @@ -17,29 +17,33 @@ plugins: - '@dotcom-tool-kit/jest' ``` -## Options + +## Tasks -| Key | Description | Default value | -|-|-|-| -| `configPath` | Path to the [Jest config file](https://jestjs.io/docs/27.x/configuration) | use Jest's own [config resolution](https://jestjs.io/docs/configuration/) | +### `Jest` -## Tasks +Runs `jest` to execute tests. +#### Task options -| Task | Description | Preconfigured hook | -|-|-|-| -| `JestLocal` | runs `jest` to execute tests | `test:local` | -| `JestCI` | runs `jest` to execute tests in the CI with the `--ci` [option](https://jestjs.io/docs/cli#--ci) | `test:ci` | +| Property | Description | Type | +| :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | +| `configPath` | Path to the [Jest config file](https://jestjs.io/docs/27.x/configuration). Use Jest's own [config resolution](https://jestjs.io/docs/configuration/) by default. | `string` | +| `ci` | Whether to run Jest in [CI mode](https://jestjs.io/docs/cli#--ci). | `true` | + +_All properties are optional._ + ## Tips -A common use case is to configure `test:local` and `test:ci` in your `.toolkitrc.yml` to run the `Eslint` task then the relevant Jest task: +A common use case is to configure `test:local` and `test:ci` in your `.toolkitrc.yml` to run the `Eslint` task then the relevant Jest task: ```yaml -hooks: +commands: test:local: - Eslint - - JestLocal + - Jest test:ci: - Eslint - - JestCI -``` \ No newline at end of file + - Jest: + ci: true +``` From 588fcb621ec803b13fac62f1b72e0514d9b4a151 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 17:02:04 +0100 Subject: [PATCH 224/321] docs(mocha): move option descriptions to schema --- lib/schemas/src/tasks/mocha.ts | 16 ++++++++++++---- plugins/mocha/readme.md | 27 +++++++++++++++------------ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/lib/schemas/src/tasks/mocha.ts b/lib/schemas/src/tasks/mocha.ts index f52438d3b..334399c7d 100644 --- a/lib/schemas/src/tasks/mocha.ts +++ b/lib/schemas/src/tasks/mocha.ts @@ -1,9 +1,17 @@ import { z } from 'zod' -export const MochaSchema = z.object({ - files: z.string().default('test/**/*.js'), - configPath: z.string().optional() -}) +export const MochaSchema = z + .object({ + files: z.string().default('test/**/*.js').describe('A file path glob to Mocha tests.'), + configPath: z + .string() + .optional() + .describe( + "Path to the [Mocha config file](https://mochajs.org/#configuring-mocha-nodejs). Uses Mocha's own [config resolution](https://mochajs.org/#priorities) by default." + ) + }) + .describe('Runs `mocha` to execute tests.') + export type MochaOptions = z.infer export const Schema = MochaSchema diff --git a/plugins/mocha/readme.md b/plugins/mocha/readme.md index 03d21e3a9..db12323cf 100644 --- a/plugins/mocha/readme.md +++ b/plugins/mocha/readme.md @@ -17,27 +17,30 @@ plugins: - '@dotcom-tool-kit/mocha' ``` -## Options + +## Tasks -| Key | Description | Default value | -|-|-|-| -| `files` | A file path glob to Mocha tests | `'test/**/*.js'` | -| `configPath` | Path to the [Mocha config file](https://mochajs.org/#configuring-mocha-nodejs) | use Mocha's own [config resolution](https://mochajs.org/#priorities) | +### `Mocha` -## Tasks +Runs `mocha` to execute tests. +#### Task options + +| Property | Description | Type | Default | +| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | :--------------- | +| `files` | A file path glob to Mocha tests. | `string` | `'test/**/*.js'` | +| `configPath` | Path to the [Mocha config file](https://mochajs.org/#configuring-mocha-nodejs). Uses Mocha's own [config resolution](https://mochajs.org/#priorities) by default. | `string` | | -| Task | Description | Preconfigured hook | -|-|-|-| -| `Mocha` | runs `mocha` to execute tests | `test:local`, `test:ci` | +_All properties are optional._ + ## Tips -### Resolving test hook conflicts +### Resolving test command conflicts -A common use case is to configure `test:local` and `test:ci` in your `.toolkitrc.yml` to run the `Eslint` task then the relevant Mocha task: +A common use case is to configure `test:local` and `test:ci` in your `.toolkitrc.yml` to run the `Eslint` task then the relevant Mocha task: ```yaml -hooks: +commands: test:local: - Eslint - Mocha From 6ce88fc3a49814bb125706f3c04678024c943763 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 17:08:12 +0100 Subject: [PATCH 225/321] docs(n-test): move option descriptions to schema --- lib/schemas/src/tasks/n-test.ts | 22 +++++++++++++++------- plugins/n-test/README.md | 27 +++++++++++++++------------ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/schemas/src/tasks/n-test.ts b/lib/schemas/src/tasks/n-test.ts index bca12edd6..ca69d4ab1 100644 --- a/lib/schemas/src/tasks/n-test.ts +++ b/lib/schemas/src/tasks/n-test.ts @@ -1,12 +1,20 @@ import { z } from 'zod' -export const SmokeTestSchema = z.object({ - browsers: z.string().array().optional(), - host: z.string().optional(), - config: z.string().optional(), - interactive: z.boolean().optional(), - header: z.record(z.string()).optional() -}) +export const SmokeTestSchema = z + .object({ + browsers: z.string().array().optional().describe('Selenium browsers to run the test against'), + host: z + .string() + .optional() + .describe( + 'Set the hostname to use for all tests. If running in an environment such as a review or staging app build that has Tool Kit state with a URL for an app to run against, that will override this option.' + ), + config: z.string().optional().describe('Path to config file used to test'), + interactive: z.boolean().optional().describe('Interactively choose which tests to run'), + header: z.record(z.string()).optional().describe('Request headers to be sent with every request') + }) + .describe('Run [n-test](https://github.com/financial-times/n-test) smoke tests against your application.') + export type SmokeTestOptions = z.infer export const Schema = SmokeTestSchema diff --git a/plugins/n-test/README.md b/plugins/n-test/README.md index 67649372c..ebf1ae2f5 100644 --- a/plugins/n-test/README.md +++ b/plugins/n-test/README.md @@ -17,18 +17,21 @@ plugins: - '@dotcom-tool-kit/n-test' ``` -## Options + +## Tasks -| Key | Description | Default value | -|-|-|-| -| `browsers` | Array; Selenium browsers to run the test against | | -| `host` | Set the hostname to use for all tests | | -| `config` | Path to config file used to test | './test/smoke.js' | -| `interactive` | Boolean; interactively choose which tests to run | `false` | -| `header` | Request headers to be sent with every request. e.g. "X-Api-Key: 1234" | | +### `NTest` -## Tasks +Run [n-test](https://github.com/financial-times/n-test) smoke tests against your application. +#### Task options + +| Property | Description | Type | +| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------- | +| `browsers` | Selenium browsers to run the test against | `Array` | +| `host` | Set the hostname to use for all tests. If running in an environment such as a review or staging app build that has Tool Kit state with a URL for an app to run against, that will override this option. | `string` | +| `config` | Path to config file used to test | `string` | +| `interactive` | Interactively choose which tests to run | `boolean` | +| `header` | Request headers to be sent with every request | `Record` | -| Task | Description | Preconfigured hooks | -|-|-|-| -| `NTest` | runs smoke tests as part of your CircleCi workflow | `test:review`, `test:staging` | +_All properties are optional._ + From c2cb872f453acaba431274a70b7b0d179ec1b78d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 17:14:44 +0100 Subject: [PATCH 226/321] docs(next-router): autogenerated readme --- lib/schemas/src/plugins/next-router.ts | 3 ++- plugins/next-router/readme.md | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/schemas/src/plugins/next-router.ts b/lib/schemas/src/plugins/next-router.ts index 346810aee..2a7136484 100644 --- a/lib/schemas/src/plugins/next-router.ts +++ b/lib/schemas/src/plugins/next-router.ts @@ -4,9 +4,10 @@ export const NextRouterSchema = z.object({ appName: z .string() .describe( - 'This needs to be same as the name your app is registered under in next-service-registry. This is usually – but not always – your system code.' + "The system's `name` field as it appears in [next-service-registry](https://next-registry.ft.com/v2). **This is often different to its Biz Ops system code**, so be sure to check." ) }) + export type NextRouterOptions = z.infer export const Schema = NextRouterSchema diff --git a/plugins/next-router/readme.md b/plugins/next-router/readme.md index 40f7345c9..422a4fe8a 100644 --- a/plugins/next-router/readme.md +++ b/plugins/next-router/readme.md @@ -19,7 +19,7 @@ plugins: ## Running an app via next-router -For an app to be loaded via the `next-router` (https://local.ft.com:5050), the app will need to be loaded before the `next-router` plugin. This is done by defining the `run:local` hook to run the application before `NextRouter` task. Here is an example full config to do that: +For an app to be loaded via the `next-router` (https://local.ft.com:5050), the app will need to be loaded before the `next-router` plugin. This is done by assigning the `run:local` command to run the application before `NextRouter` task. Here is an example full config to do that: ```yml plugins: @@ -27,7 +27,7 @@ plugins: - '@dotcom-tool-kit/nodemon' - '@dotcom-tool-kit/doppler' -hooks: +commands: run:local: - Nodemon - NextRouter @@ -39,14 +39,14 @@ options: project: '[systemCode]' # corresponding doppler project name ``` -## Options + +## Plugin-wide options -| Key | Description | Default value | Required | -|-|-|-|-| -| `appName` | the system's `name` field as it appears in [next-service-registry](https://next-registry.ft.com/v2), which is _often different to its `code` value so be sure to check_) | | ✅ | +### `@dotcom-tool-kit/next-router` -## Tasks +| Property | Description | Type | +| :----------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | +| **`appName`** (\*) | The system's `name` field as it appears in [next-service-registry](https://next-registry.ft.com/v2). **This is often different to its Biz Ops system code**, so be sure to check. | `string` | -| Task | Description | Default hooks | -|-|-|-| -| `NextRouter` | Run the application via the `next-router` | `run:local` | +_(\*) Required._ + From cff4ee3ed2fe937712bd58823fa3fbf48f3d3329 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 17:20:17 +0100 Subject: [PATCH 227/321] docs(node): move node options description to schema --- lib/schemas/src/tasks/node.ts | 23 +++++++++++++++++------ plugins/node/readme.md | 25 ++++++++++++++----------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/lib/schemas/src/tasks/node.ts b/lib/schemas/src/tasks/node.ts index e0757b7a1..993fec9b3 100644 --- a/lib/schemas/src/tasks/node.ts +++ b/lib/schemas/src/tasks/node.ts @@ -1,11 +1,22 @@ import { z } from 'zod' -export const NodeSchema = z.object({ - entry: z.string().default('./server/app.js'), - args: z.string().array().optional(), - useDoppler: z.boolean().default(true), - ports: z.union([z.number().array(), z.literal(false)]).default([3001, 3002, 3003]) -}) +export const NodeSchema = z + .object({ + entry: z.string().default('./server/app.js').describe('path to the node application'), + args: z.string().array().optional().describe('additional arguments to pass to your application'), + useDoppler: z + .boolean() + .default(true) + .describe('whether to run the application with environment variables from Doppler'), + ports: z + .union([z.number().array(), z.literal(false)]) + .default([3001, 3002, 3003]) + .describe( + "ports to try to bind to for this application. set to `false` for an entry point that wouldn't bind to a port, such as a worker process or one-off script." + ) + }) + .describe('Run a Node.js application for local development.') + export type NodeOptions = z.infer export const Schema = NodeSchema diff --git a/plugins/node/readme.md b/plugins/node/readme.md index e78f3d3d8..383023af7 100644 --- a/plugins/node/readme.md +++ b/plugins/node/readme.md @@ -19,17 +19,20 @@ plugins: - '@dotcom-tool-kit/node' ``` -## Options + +## Tasks -| Key | Description | Default value | -|-|-|-| -| `entry` | path to the node application | `'./server/app.js'` | -| `args` | additional arguments to pass to your application | `[]` | -| `useVault` | option to run the application with environment variables from Vault | `true` | -| `ports` | ports to try to bind to for this application | `[3001, 3002, 3003]` | +### `Node` -## Tasks +Run a Node.js application for local development. +#### Task options + +| Property | Description | Type | Default | +| :----------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------- | :------------------ | +| `entry` | path to the node application | `string` | `'./server/app.js'` | +| `args` | additional arguments to pass to your application | `Array` | | +| `useDoppler` | whether to run the application with environment variables from Doppler | `boolean` | `true` | +| `ports` | ports to try to bind to for this application. set to `false` for an entry point that wouldn't bind to a port, such as a worker process or one-off script. | `Array \| false` | `[3001,3002,3003]` | -| Task | Description | Default hooks | -|-|-|-| -| `Node` | Run node application | `run:local` | +_All properties are optional._ + From 76317c0a497d438eff8296d1fb3883b1390e5b49 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 17:23:24 +0100 Subject: [PATCH 228/321] docs(nodemon): move options description to schema --- lib/schemas/src/tasks/nodemon.ts | 27 +++++++++++++++++++++------ plugins/nodemon/readme.md | 25 ++++++++++++++----------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/lib/schemas/src/tasks/nodemon.ts b/lib/schemas/src/tasks/nodemon.ts index c79d2a26c..940e5e7bb 100644 --- a/lib/schemas/src/tasks/nodemon.ts +++ b/lib/schemas/src/tasks/nodemon.ts @@ -1,11 +1,26 @@ import { z } from 'zod' -export const NodemonSchema = z.object({ - entry: z.string().default('./server/app.js'), - configPath: z.string().optional(), - useDoppler: z.boolean().default(true), - ports: z.union([z.number().array(), z.literal(false)]).default([3001, 3002, 3003]) -}) +export const NodemonSchema = z + .object({ + entry: z.string().default('./server/app.js').describe('path to the node application'), + configPath: z + .string() + .optional() + .describe( + "path to a Nodemon config file. defaults to Nodemon's [automatic config resolution](https://github.com/remy/nodemon#config-files)." + ), + useDoppler: z + .boolean() + .default(true) + .describe('whether to run the application with environment variables from Doppler'), + ports: z + .union([z.number().array(), z.literal(false)]) + .default([3001, 3002, 3003]) + .describe( + "ports to try to bind to for this application. set to `false` for an entry point that wouldn't bind to a port, such as a worker process or one-off script." + ) + }) + .describe('Run an application with `nodemon` for local development.') export type NodemonOptions = z.infer diff --git a/plugins/nodemon/readme.md b/plugins/nodemon/readme.md index 94e3a3344..779b36cab 100644 --- a/plugins/nodemon/readme.md +++ b/plugins/nodemon/readme.md @@ -17,17 +17,20 @@ plugins: - '@dotcom-tool-kit/nodemon' ``` -## Options + +## Tasks -| Key | Description | Default value | -|-|-|-| -| `entry` | path to the node application | `'./server/app.js'` | -| `configPath` | path to custom nodemon config | [automatic config resolution](https://github.com/remy/nodemon#config-files) | -| `useVault` | option to run the application with environment variables from Vault | `true` | -| `ports` | ports to try to bind to for this application | `[3001, 3002, 3003]` | +### `Nodemon` -## Tasks +Run an application with `nodemon` for local development. +#### Task options + +| Property | Description | Type | Default | +| :----------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------- | :------------------ | +| `entry` | path to the node application | `string` | `'./server/app.js'` | +| `configPath` | path to a Nodemon config file. defaults to Nodemon's [automatic config resolution](https://github.com/remy/nodemon#config-files). | `string` | | +| `useDoppler` | whether to run the application with environment variables from Doppler | `boolean` | `true` | +| `ports` | ports to try to bind to for this application. set to `false` for an entry point that wouldn't bind to a port, such as a worker process or one-off script. | `Array \| false` | `[3001,3002,3003]` | -| Task | Description | Default hooks | -|-|-|-| -| `Nodemon` | Run application with `nodemon` | `run:local` | +_All properties are optional._ + From e4cf9f1d310a3a23c0dce8e1765220aa2c749be0 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 17:25:22 +0100 Subject: [PATCH 229/321] docs(pa11y): move docs to schema descriptinos --- lib/schemas/src/tasks/pa11y.ts | 8 +++++--- plugins/pa11y/readme.md | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/schemas/src/tasks/pa11y.ts b/lib/schemas/src/tasks/pa11y.ts index 704580ac2..261d3f552 100644 --- a/lib/schemas/src/tasks/pa11y.ts +++ b/lib/schemas/src/tasks/pa11y.ts @@ -1,8 +1,10 @@ import { z } from 'zod' -export const Pa11ySchema = z.object({ - configFile: z.string().optional() -}) +export const Pa11ySchema = z + .object({ + configFile: z.string().optional().describe('Path to the config file') + }) + .describe('runs `pa11y-ci` to execute Pa11y tests') export type Pa11yOptions = z.infer diff --git a/plugins/pa11y/readme.md b/plugins/pa11y/readme.md index 4e278410c..9741615c5 100644 --- a/plugins/pa11y/readme.md +++ b/plugins/pa11y/readme.md @@ -23,17 +23,20 @@ plugins: - '@dotcom-tool-kit/pa11y' ``` -## Options + +## Tasks -| Key | Description | Default value | -|-|-|-| -| `configFile` | Path to the config file | `.pa11yci.js` | +### `Pa11y` -## Tasks +runs `pa11y-ci` to execute Pa11y tests +#### Task options + +| Property | Description | Type | +| :----------- | :---------------------- | :------- | +| `configFile` | Path to the config file | `string` | -| Task | Description | Preconfigured hook | -|-|-|-| -| `Pa11y` | runs `pa11y-ci` to execute Pa11y tests | `test:local` | +_All properties are optional._ + ## To note From 261fc65ed06551ff77d5da75bb4af106241a1863 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 23 Apr 2024 17:54:45 +0100 Subject: [PATCH 230/321] docs(package-json-hook): add readme --- lib/schemas/src/hooks/package-json.ts | 34 ++++++++++++ plugins/package-json-hook/readme.md | 76 +++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 plugins/package-json-hook/readme.md diff --git a/lib/schemas/src/hooks/package-json.ts b/lib/schemas/src/hooks/package-json.ts index 13d1f43ce..8dfdd7e4c 100644 --- a/lib/schemas/src/hooks/package-json.ts +++ b/lib/schemas/src/hooks/package-json.ts @@ -12,6 +12,40 @@ export const PackageJsonSchema = z.record( ]) ) ) + .describe(`This hook accepts a nested object with a structure that matches the generated output in \`package.json\`. The values are used as Tool Kit command names to run. You can provide a single command or an array; multiple commands are concatenated in order. + +For more complex use cases, you can provide an object instead of a command. The object must contain keys \`commands\` (as above), and \`trailingString\` (which will be appended to the resulting \`dotcom-tool-kit\` CLI invocation). This is useful for tasks that accept a list of files after a trailing \`--\`. + +Options provided in your repository's \`.toolkitrc.yml\` for this hook are merged with any Tool Kit plugin that also provides options for the hook. + +For example, configuring this hook with the following options: + +~~~yml +options: + hooks: + - PackageJson: + scripts: + start: 'run:local' + customScript: + commands: + - custom:one + - custom:two + trailingString: '--' +~~~ + +will result in the following output in \`package.json\`: + +~~~json +{ + "scripts": { + "start": "dotcom-tool-kit run:local", + "customScript": "dotcom-tool-kit custom:one custom:two --" + } +} +~~~ + + +## Hooks + +### `PackageJson` + +This hook accepts a nested object with a structure that matches the generated output in `package.json`. The values are used as Tool Kit command names to run. You can provide a single command or an array; multiple commands are concatenated in order. + +For more complex use cases, you can provide an object instead of a command. The object must contain keys `commands` (as above), and `trailingString` (which will be appended to the resulting `dotcom-tool-kit` CLI invocation). This is useful for tasks that accept a list of files after a trailing `--`. + +Options provided in your repository's `.toolkitrc.yml` for this hook are merged with any Tool Kit plugin that also provides options for the hook. + +For example, configuring this hook with the following options: + +~~~yml +options: + hooks: + - PackageJson: + scripts: + start: 'run:local' + customScript: + commands: + - custom:one + - custom:two + trailingString: '--' +~~~ + +will result in the following output in `package.json`: + +~~~json +{ + "scripts": { + "start": "dotcom-tool-kit run:local", + "customScript": "dotcom-tool-kit custom:one custom:two --" + } +} +~~~ + + From 1b61913e44973cf781abd1399fa9ed9294c2d534 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 24 Apr 2024 08:57:04 +0100 Subject: [PATCH 231/321] docs(prettier): autogenerate options docs --- lib/schemas/src/tasks/prettier.ts | 25 ++++++++++++++++++++----- plugins/prettier/readme.md | 27 +++++++++++++-------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/lib/schemas/src/tasks/prettier.ts b/lib/schemas/src/tasks/prettier.ts index 75f0b03c3..7ca2af484 100644 --- a/lib/schemas/src/tasks/prettier.ts +++ b/lib/schemas/src/tasks/prettier.ts @@ -1,10 +1,25 @@ import { z } from 'zod' -export const PrettierSchema = z.object({ - files: z.string().array().or(z.string()).default(['**/*.{js,jsx,ts,tsx}']), - configFile: z.string().optional(), - ignoreFile: z.string().default('.prettierignore') -}) +export const PrettierSchema = z + .object({ + files: z + .string() + .array() + .or(z.string()) + .default(['**/*.{js,jsx,ts,tsx}']) + .describe('glob pattern of files to run Prettier on.'), + configFile: z + .string() + .optional() + .describe( + "path to a Prettier config file to use. Uses Prettier's built-in [config resolution](https://prettier.io/docs/en/configuration.html) by default." + ), + ignoreFile: z + .string() + .default('.prettierignore') + .describe('path to a Prettier [ignore file](https://prettier.io/docs/en/ignore).') + }) + .describe('Format files with `prettier`.') export type PrettierOptions = z.infer diff --git a/plugins/prettier/readme.md b/plugins/prettier/readme.md index ac7a217f8..a3a59a330 100644 --- a/plugins/prettier/readme.md +++ b/plugins/prettier/readme.md @@ -1,6 +1,6 @@ # @dotcom-tool-kit/prettier -This plugin is for adding prettier onto your apps. +Tool Kit plugin to format your source code with [Prettier](https://prettier.io). ## Installation @@ -17,20 +17,19 @@ plugins: - '@dotcom-tool-kit/prettier' ``` -And install this plugin's hooks: + +## Tasks -```sh -npx dotcom-tool-kit --install -``` - -This will modify your `package.json`. You should commit this change. +### `Prettier` -### Options +Format files with `prettier`. +#### Task options -| Key | Description | Default value | -|-|-|-| -| `files` | A required Array of strings of filepath(s) or filepath pattern(s) to be formatted | `['{,!(node_modules)/**/}*.js']` | -| `configOptions` | An optional prettier configuration object |
`{`
` singleQuote: true,`
` useTabs: true,`
` bracketSpacing: true,`
` arrowParens: 'always',`
` trailingComma: 'none'`
`}`
| -| `configFile` | An optional String that specifies the prettier configuration file (.prettierrc.json). The configuration file will be resolved starting from the location of the file being formatted, and searching up the file tree until a config file is (or isn’t) found. If the configFile is not found the prettier plugin will default to configOptions. | `configOptions` value | +| Property | Description | Type | Default | +| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------ | :------------------------- | +| `files` | glob pattern of files to run Prettier on. | `Array \| string` | `["**/*.{js,jsx,ts,tsx}"]` | +| `configFile` | path to a Prettier config file to use. Uses Prettier's built-in [config resolution](https://prettier.io/docs/en/configuration.html) by default. | `string` | | +| `ignoreFile` | path to a Prettier [ignore file](https://prettier.io/docs/en/ignore). | `string` | `'.prettierignore'` | -For more information on prettier configuration, visit the [Prettier docs](https://prettier.io/docs/en/configuration.html). +_All properties are optional._ + From 60d8b74c9244716a01fc632124af9e107c8af42a Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 24 Apr 2024 09:07:08 +0100 Subject: [PATCH 232/321] docs(typescript): autogenerate options docs --- lib/schemas/src/tasks/typescript.ts | 29 +++++++++++++++++++++++------ plugins/typescript/readme.md | 25 ++++++++++++++----------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/lib/schemas/src/tasks/typescript.ts b/lib/schemas/src/tasks/typescript.ts index 8f188eb14..4dde98c62 100644 --- a/lib/schemas/src/tasks/typescript.ts +++ b/lib/schemas/src/tasks/typescript.ts @@ -1,11 +1,28 @@ import { z } from 'zod' -export const TypeScriptSchema = z.object({ - configPath: z.string().optional(), - build: z.literal(true).optional(), - watch: z.literal(true).optional(), - noEmit: z.literal(true).optional() -}) +export const TypeScriptSchema = z + .object({ + configPath: z + .string() + .optional() + .describe( + "to the [TypeScript config file](https://www.typescriptlang.org/tsconfig). Uses TypeScript's own [tsconfig.json resolution](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#using-tsconfigjson-or-jsconfigjson) by default" + ), + build: z + .literal(true) + .optional() + .describe( + 'Run Typescript in [build mode](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript).' + ), + watch: z.literal(true).optional().describe('Run Typescript in watch mode.'), + noEmit: z + .literal(true) + .optional() + .describe( + 'Run Typescript with `--noEmit`, for checking your types without outputting compiled Javascript.' + ) + }) + .describe('Compile code with `tsc`.') export type TypeScriptOptions = z.infer diff --git a/plugins/typescript/readme.md b/plugins/typescript/readme.md index a0de9f07d..9162ba753 100644 --- a/plugins/typescript/readme.md +++ b/plugins/typescript/readme.md @@ -17,17 +17,20 @@ plugins: - '@dotcom-tool-kit/typescript' ``` -## Options + +## Tasks -| Key | Description | Default value | -|-|-|-| -| `configPath` | Path to the [TypeScript config file](https://www.typescriptlang.org/tsconfig) | use TypeScript's own [tsconfig.json resolution](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#using-tsconfigjson-or-jsconfigjson) | -| `extraArgs` | Extra [arguments](https://www.typescriptlang.org/docs/handbook/compiler-options.html) to pass to the tsc CLI that can't be set in `tsconfig.json` | `[]` +### `TypeScript` -## Tasks +Compile code with `tsc`. +#### Task options + +| Property | Description | Type | +| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- | +| `configPath` | to the [TypeScript config file](https://www.typescriptlang.org/tsconfig). Uses TypeScript's own [tsconfig.json resolution](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#using-tsconfigjson-or-jsconfigjson) by default | `string` | +| `build` | Run Typescript in [build mode](https://www.typescriptlang.org/docs/handbook/project-references.html#build-mode-for-typescript). | `true` | +| `watch` | Run Typescript in watch mode. | `true` | +| `noEmit` | Run Typescript with `--noEmit`, for checking your types without outputting compiled Javascript. | `true` | -| Task | Description | Preconfigured hook | -|-|-|-| -| `TypeScriptBuild` | runs `tsc` to compile TypeScript to JavaScript | `build:local`, `build:ci`, `build:remote` | -| `TypeScriptWatch` | rebuild project on every project file change | `run:local` | -| `TypeScriptTest` | type check TypeScript code without emitting code | `test:local` | +_All properties are optional._ + From 1eb0d6bd1a1e15e92899f9a3e7784a1928e617e4 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 24 Apr 2024 10:26:16 +0100 Subject: [PATCH 233/321] feat(upload-assets-to-s3)!: remove legacy environment variable handling also throw if they're not present with a useful message --- lib/schemas/src/tasks/upload-assets-to-s3.ts | 15 ++++++--- .../src/tasks/upload-assets-to-s3.ts | 33 +++++++++++-------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/lib/schemas/src/tasks/upload-assets-to-s3.ts b/lib/schemas/src/tasks/upload-assets-to-s3.ts index 9906ccc50..055347bcb 100644 --- a/lib/schemas/src/tasks/upload-assets-to-s3.ts +++ b/lib/schemas/src/tasks/upload-assets-to-s3.ts @@ -1,10 +1,16 @@ import { z } from 'zod' export const UploadAssetsToS3Schema = z.object({ - accessKeyIdEnvVar: z.string().optional(), - secretAccessKeyEnvVar: z.string().optional(), - accessKeyId: z.string().default('aws_access_hashed_assets'), // @deprecated: use accessKeyIdEnvVar instead - secretAccessKey: z.string().default('aws_secret_hashed_assets'), // @deprecated: use secretAccessKeyEnvVar instead + accessKeyIdEnvVar: z + .string() + .default('AWS_ACCESS_HASHED_ASSETS') + .describe( + "variable name of the project's aws access key id. If uploading to multiple buckets the same credentials will need to work for all" + ), + secretAccessKeyEnvVar: z + .string() + .default('AWS_SECRET_HASHED_ASSETS') + .describe("variable name of the project's aws secret access key"), directory: z.string().default('public'), reviewBucket: z.string().array().default(['ft-next-hashed-assets-preview']), prodBucket: z.string().array().default(['ft-next-hashed-assets-prod']), @@ -13,6 +19,7 @@ export const UploadAssetsToS3Schema = z.object({ extensions: z.string().default('js,css,map,gz,br,png,jpg,jpeg,gif,webp,svg,ico,json'), cacheControl: z.string().default('public, max-age=31536000, stale-while-revalidate=60, stale-if-error=3600') }) + export type UploadAssetsToS3Options = z.infer export const Schema = UploadAssetsToS3Schema diff --git a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts index a2fad5d4d..719a19173 100644 --- a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts +++ b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts @@ -76,24 +76,29 @@ export default class UploadAssetsToS3 extends Task<{ task: typeof UploadAssetsTo throw new ToolKitError(`no files found at the provided directory: ${options.directory}`) } - // HACK:20231006:IM Doppler doesn't support secrets with lowercase - // characters so let's check if the provided AWS environment variable name - // is available in all caps as will be the case when running our migration - // script. - const checkUppercaseName = (envName: string): string | undefined => { - return process.env[envName] ?? process.env[envName.toUpperCase()] + const accessKeyId = process.env[options.accessKeyIdEnvVar] + const secretAccessKey = process.env[options.secretAccessKeyEnvVar] + + if (!accessKeyId || !secretAccessKey) { + const missingVars = [ + !accessKeyId ? options.accessKeyIdEnvVar : false, + !secretAccessKey ? options.secretAccessKeyEnvVar : false + ] + + const error = new ToolKitError( + `environment variable${missingVars.length > 1 ? 's' : ''} ${missingVars.join(' and ')} not set` + ) + error.details = `if your AWS credentials are stored in different environment variables, set the ${styles.code( + 'accessKeyIdEnvVar' + )} and ${styles.code('secretAccessKeyEnvVar')} options for this task.` + throw error } + const s3 = new S3Client({ region: options.region, - // will fallback to default value for accessKeyId if neither - // accessKeyIdEnvVar nor accessKeyId have been provided as options credentials: { - accessKeyId: - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - checkUppercaseName(options.accessKeyIdEnvVar ?? options.accessKeyId)!, - secretAccessKey: - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - checkUppercaseName(options.secretAccessKeyEnvVar ?? options.secretAccessKey)! + accessKeyId, + secretAccessKey } }) From 39d3e43731a195f9443c63bad1c9d87d4917b336 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 24 Apr 2024 10:47:17 +0100 Subject: [PATCH 234/321] docs(upload-assets-to-s3): autogenerate options documentation --- lib/schemas/src/tasks/upload-assets-to-s3.ts | 71 ++++++++++++++------ plugins/upload-assets-to-s3/README.md | 46 ++++++------- 2 files changed, 73 insertions(+), 44 deletions(-) diff --git a/lib/schemas/src/tasks/upload-assets-to-s3.ts b/lib/schemas/src/tasks/upload-assets-to-s3.ts index 055347bcb..40e894f24 100644 --- a/lib/schemas/src/tasks/upload-assets-to-s3.ts +++ b/lib/schemas/src/tasks/upload-assets-to-s3.ts @@ -1,24 +1,57 @@ import { z } from 'zod' -export const UploadAssetsToS3Schema = z.object({ - accessKeyIdEnvVar: z - .string() - .default('AWS_ACCESS_HASHED_ASSETS') - .describe( - "variable name of the project's aws access key id. If uploading to multiple buckets the same credentials will need to work for all" - ), - secretAccessKeyEnvVar: z - .string() - .default('AWS_SECRET_HASHED_ASSETS') - .describe("variable name of the project's aws secret access key"), - directory: z.string().default('public'), - reviewBucket: z.string().array().default(['ft-next-hashed-assets-preview']), - prodBucket: z.string().array().default(['ft-next-hashed-assets-prod']), - region: z.string().default('eu-west-1'), - destination: z.string().default('hashed-assets/page-kit'), - extensions: z.string().default('js,css,map,gz,br,png,jpg,jpeg,gif,webp,svg,ico,json'), - cacheControl: z.string().default('public, max-age=31536000, stale-while-revalidate=60, stale-if-error=3600') -}) +export const UploadAssetsToS3Schema = z + .object({ + accessKeyIdEnvVar: z + .string() + .default('AWS_ACCESS_HASHED_ASSETS') + .describe( + "variable name of the project's aws access key id. If uploading to multiple buckets the same credentials will need to work for all" + ), + secretAccessKeyEnvVar: z + .string() + .default('AWS_SECRET_HASHED_ASSETS') + .describe("variable name of the project's aws secret access key"), + directory: z + .string() + .default('public') + .describe('the folder in the project whose contents will be uploaded to S3'), + reviewBucket: z + .string() + .array() + .default(['ft-next-hashed-assets-preview']) + .describe('the development or test S3 bucket'), + prodBucket: z + .string() + .array() + .default(['ft-next-hashed-assets-prod']) + .describe( + "production S3 bucket(s). The same files will be uploaded to each. **Note**: most Customer Products buckets that have a `prod` and `prod-us` version are already configured in AWS to replicate file changes from one to the other so you don't need to specify both here. Also, if multiple buckets are specified the same credentials will need to be valid for both for the upload to be successful." + ), + region: z + .string() + .default('eu-west-1') + .describe( + 'the AWS region your buckets are stored in (let the Platforms team know if you need to upload to multiple buckets in multiple regions).' + ), + destination: z + .string() + .default('hashed-assets/page-kit') + .describe( + "the destination folder for uploaded assets. Set to `''` to upload assets to the top level of the bucket" + ), + extensions: z + .string() + .default('js,css,map,gz,br,png,jpg,jpeg,gif,webp,svg,ico,json') + .describe('file extensions to be uploaded to S3'), + cacheControl: z + .string() + .default('public, max-age=31536000, stale-while-revalidate=60, stale-if-error=3600') + .describe( + 'header that controls how long your files stay in a CloudFront cache before CloudFront forwards another request to your origin' + ) + }) + .describe('Upload files to an AWS S3 bucket.') export type UploadAssetsToS3Options = z.infer diff --git a/plugins/upload-assets-to-s3/README.md b/plugins/upload-assets-to-s3/README.md index e8466c8af..11606078f 100644 --- a/plugins/upload-assets-to-s3/README.md +++ b/plugins/upload-assets-to-s3/README.md @@ -17,32 +17,28 @@ plugins: - '@dotcom-tool-kit/upload-assets-to-s3' ``` + +## Tasks -## Options -| Key | Description | Default value | -|-|-|-| -| `accessKeyIdEnvVar` | variable name of the project's aws access key id. If uploading to multiple buckets the same credentials will need to work for all. | no default value - for backwards compatability the plugin falls back to the default value for `accessKeyId` | -| `secretAccessKeyEnvVar` | variable name of the project's aws secret access key | no default value - for backwards compatability the plugin falls back to the default value for `secretAccessKey` | -| `accessKeyId` | **DEPRECATED** variable name of the project's aws access key id | 'aws_access_hashed_assets' | -| `secretAccessKey` | **DEPRECATED** variable name of the project's aws secret access key | 'aws_secret_hashed_assets' | -| `directory` | the folder in the project whose contents will be uploaded to S3 | 'public' | -| `reviewBucket` | the development or test S3 bucket | `['ft-next-hashed-assets-preview']` | -| `prodBucket` | production S3 bucket/s; an array of strings. The same files will be uploaded to each. _Note: most Customer Products buckets that have a `prod` and `prod-us` version are already configured in AWS to replicate file changes from one to the other so you don't need to specify both here. Also, if multiple buckets are specified the same credentials will need to be valid for both for the upload to be successful_ | `['ft-next-hashed-assets-prod']` | -| `region` | the AWS region your buckets are stored in (let the Platforms team know if you need to upload to multiple buckets in multiple regions) | eu-west-1 | -| `destination` | the destination folder for uploaded assets. Set to `''` to upload assets to the top level of the bucket | 'hashed-assets/page-kit' | -| `extensions` | file extensions to be uploaded to S3 | 'js,css,map,gz,br,png,jpg,jpeg,gif,webp,svg,ico,json' | -| `cacheControl` | header that controls how long your files stay in a CloudFront cache before CloudFront forwards another request to your origin | 'public, max-age=31536000, stale-while-revalidate=60, stale-if-error=3600' | - -Example: -```yml -'@dotcom-tool-kit/upload-assets-to-s3': - '@dotcom-tool-kit/upload-assets-to-s3': - accessKeyId: AWS_ACCESS - secretAccessKey: AWS_KEY - prodBucket: ['ft-next-service-registry-prod'] - reviewBucket: ['ft-next-service-registry-dev'] - destination: '' -``` +### `UploadAssetsToS3` + +Upload files to an AWS S3 bucket. +#### Task options + +| Property | Description | Type | Default | +| :---------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------- | :--------------------------------------------------------------------------- | +| `accessKeyIdEnvVar` | variable name of the project's aws access key id. If uploading to multiple buckets the same credentials will need to work for all | `string` | `'AWS_ACCESS_HASHED_ASSETS'` | +| `secretAccessKeyEnvVar` | variable name of the project's aws secret access key | `string` | `'AWS_SECRET_HASHED_ASSETS'` | +| `directory` | the folder in the project whose contents will be uploaded to S3 | `string` | `'public'` | +| `reviewBucket` | the development or test S3 bucket | `Array` | `["ft-next-hashed-assets-preview"]` | +| `prodBucket` | production S3 bucket(s). The same files will be uploaded to each. **Note**: most Customer Products buckets that have a `prod` and `prod-us` version are already configured in AWS to replicate file changes from one to the other so you don't need to specify both here. Also, if multiple buckets are specified the same credentials will need to be valid for both for the upload to be successful. | `Array` | `["ft-next-hashed-assets-prod"]` | +| `region` | the AWS region your buckets are stored in (let the Platforms team know if you need to upload to multiple buckets in multiple regions). | `string` | `'eu-west-1'` | +| `destination` | the destination folder for uploaded assets. Set to `''` to upload assets to the top level of the bucket | `string` | `'hashed-assets/page-kit'` | +| `extensions` | file extensions to be uploaded to S3 | `string` | `'js,css,map,gz,br,png,jpg,jpeg,gif,webp,svg,ico,json'` | +| `cacheControl` | header that controls how long your files stay in a CloudFront cache before CloudFront forwards another request to your origin | `string` | `'public, max-age=31536000, stale-while-revalidate=60, stale-if-error=3600'` | + +_All properties are optional._ + ## Testing uploads using the review bucket From bebfed8802ce5ea3403bf817e93f376cf31c0e85 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Wed, 24 Apr 2024 10:55:27 +0100 Subject: [PATCH 235/321] docs(webpack): autogenerate option docs --- lib/schemas/src/tasks/webpack.ts | 18 +++++++++++---- plugins/webpack/readme.md | 39 +++++++++++++++++--------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/lib/schemas/src/tasks/webpack.ts b/lib/schemas/src/tasks/webpack.ts index ab93af618..6b5de4e6c 100644 --- a/lib/schemas/src/tasks/webpack.ts +++ b/lib/schemas/src/tasks/webpack.ts @@ -1,10 +1,18 @@ import { z } from 'zod' -export const WebpackSchema = z.object({ - configPath: z.string().optional(), - envName: z.union([z.literal('production'), z.literal('development')]), - watch: z.boolean().optional() -}) +export const WebpackSchema = z + .object({ + configPath: z + .string() + .optional() + .describe('path to a Webpack config file. Webpack will default to `webpack.config.js`.'), + envName: z + .union([z.literal('production'), z.literal('development')]) + .describe("set Webpack's [mode](https://webpack.js.org/configuration/mode/)."), + watch: z.boolean().optional().describe('run Webpack in watch mode') + }) + .describe('Bundle code with `webpack`.') + export type WebpackOptions = z.infer export const Schema = WebpackSchema diff --git a/plugins/webpack/readme.md b/plugins/webpack/readme.md index 54951014b..67898bc3d 100644 --- a/plugins/webpack/readme.md +++ b/plugins/webpack/readme.md @@ -17,37 +17,40 @@ plugins: - '@dotcom-tool-kit/webpack' ``` -You will need plugins that provides hooks to run the `Webpack*` tasks. - ### Building with Webpack locally -For local development, by default the `WebpackDevelopment` task runs on the `build:local` hook, and `WebpackWatch` runs on `run:local`. One plugin that provides these hooks is [`npm`](../npm), allowing you to run Webpack with `npm run build` and `npm start`. `WebpackWatch` runs Webpack in the background, allowing it to run alongside your other tasks that run on `run:local`, which lets you run e.g. your app with the [`node`](../node) plugin in parallel with Webpack. +For local development, by default the `WebpackDevelopment` task runs on the `build:local` command, and `WebpackWatch` runs on `run:local`. One plugin that provides these commands is [`npm`](../npm), allowing you to run Webpack with `npm run build` and `npm start`. `WebpackWatch` runs Webpack in the background, allowing it to run alongside your other tasks that run on `run:local`, which lets you run e.g. your app with the [`node`](../node) plugin in parallel with Webpack. ### Building with Webpack on CI and remote apps -The `WebpackProduction` task runs on the `build:ci` and `build:remote` hooks by default. `build:ci` is for compiling an app's source in CI jobs, and is provided by plugins like [`circleci`](../circleci/). `build:remote` compiles an app for running on a production or testing server, and can be provided by plugins like [`heroku`](../heroku/). +The `WebpackProduction` task runs on the `build:ci` and `build:remote` commands by default. `build:ci` is for compiling an app's source in CI jobs, and is provided by plugins like [`circleci`](../circleci/). `build:remote` compiles an app for running on a production or testing server, and can be provided by plugins like [`heroku`](../heroku/). -### Running on another hook -You can also configure Webpack to run on any other hook; for example, if you want to run it with `npm run test` via the `npm` plugin, you can manually configure Webpack to run on `npm`'s `test:local` hook: +### Running on another command +You can also configure Webpack to run on any other command; for example, if you want to run it with `npm run test` via the `npm` plugin, you can manually configure Webpack to run on `npm`'s `test:local` command: ```yml plugins: - '@dotcom-tool-kit/webpack' - '@dotcom-tool-kit/npm' -hooks: - 'test:local': WebpackDevelopment +command: + 'test:local': + Webpack: + mode: development ``` -## Options + +## Tasks + +### `Webpack` -| Key | Description | Default value | -|-|-|-| -| `configPath` | An optional path to your Webpack config file | none | +Bundle code with `webpack`. +#### Task options -## Tasks +| Property | Description | Type | +| :----------------- | :-------------------------------------------------------------------------- | :------------------------------ | +| `configPath` | path to a Webpack config file. Webpack will default to `webpack.config.js`. | `string` | +| **`envName`** (\*) | set Webpack's [mode](https://webpack.js.org/configuration/mode/). | `'production' \| 'development'` | +| `watch` | run Webpack in watch mode | `boolean` | -| Task | Description | Default hooks | -|-|-|-| -| `WebpackDevelopment` | Run Webpack in development mode | `build:local` | -| `WebpackProduction` | Run Webpack in production mode | `build:ci`, `build:remote` | -| `WebpackWatch` | Run Webpack in watch mode in the background | `run:local` | +_(\*) Required._ + From 2dbb88aee0af9209864005ad3f802c3e859b8749 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 09:18:47 +0100 Subject: [PATCH 236/321] build: don't print an empty options schema --- scripts/generate-docs.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index 5ddd41eb8..4ad68e05e 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -59,8 +59,18 @@ async function formatPluginSchemas(plugin) { ` } +const EMPTY_OBJECT_SCHEMA = `#### Task options + +| Property | Type | +| :------- | :--- | + +_All properties are optional._` + function postProcessMarkdown(markdown) { - return markdown.replace(/^#/gm, '##').replace(/_Object containing the following properties:_\n\n/g, '') + return markdown + .replace(/^#/gm, '##') + .replace(/_Object containing the following properties:_\n\n/g, '') + .replaceAll(EMPTY_OBJECT_SCHEMA, '') } const BEGIN_COMMENT = '\n' From 1f2d5c549bb7d8565d63c0a0487c4c4e0cf33172 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 09:19:19 +0100 Subject: [PATCH 237/321] docs(npm): autogenerate task docs --- lib/schemas/src/tasks.ts | 3 +++ plugins/npm/readme.md | 19 +++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 1380fb518..aa0cc316d 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -14,6 +14,7 @@ import { SmokeTestSchema } from './tasks/n-test' import { CypressSchema } from './tasks/cypress' import { HerokuProductionSchema } from './tasks/heroku-production' import { ServerlessRunSchema } from './tasks/serverless-run' +import { z } from 'zod' export const TaskSchemas = { Babel: BabelSchema, @@ -24,6 +25,8 @@ export const TaskSchemas = { Mocha: MochaSchema, Node: NodeSchema, Nodemon: NodemonSchema, + NpmPrune: z.object({}).describe('Prune development npm dependencies.'), + NpmPublish: z.object({}).describe('Publish package to the npm registry.'), NTest: SmokeTestSchema, Pa11y: Pa11ySchema, Prettier: PrettierSchema, diff --git a/plugins/npm/readme.md b/plugins/npm/readme.md index 02b5e7c50..3a59e6eec 100644 --- a/plugins/npm/readme.md +++ b/plugins/npm/readme.md @@ -19,17 +19,16 @@ plugins: - '@dotcom-tool-kit/npm' ``` -And install this plugin's hooks: + +## Tasks + +### `NpmPrune` + +Prune development npm dependencies. -```sh -npx dotcom-tool-kit --install -``` -This will modify your `package.json`. You should commit this change. +### `NpmPublish` -## Hooks +Publish package to the npm registry. -| Event | Description | Installed to...| -|-|-|-| -| `build:local` | Compile any assets or code required for your app to run locally, in development. | `build` script in `package.json` (i.e. run from `npm run build`) | -| `test:local` | Run your app's test suite locally, during development. | `test` script in `package.json` (i.e. run from `npm run test`) + From 8d0099a3232619f41593eefa6416c468cbff50cc Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 09:29:24 +0100 Subject: [PATCH 238/321] docs(lint-staged): autogenerate task docs --- lib/schemas/src/tasks.ts | 1 + plugins/lint-staged/readme.md | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index aa0cc316d..e9ddde34a 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -22,6 +22,7 @@ export const TaskSchemas = { Eslint: ESLintSchema, HerokuProduction: HerokuProductionSchema, Jest: JestSchema, + LintStaged: z.object({}).describe('Run `lint-staged` in your repo, for use with git hooks.'), Mocha: MochaSchema, Node: NodeSchema, Nodemon: NodemonSchema, diff --git a/plugins/lint-staged/readme.md b/plugins/lint-staged/readme.md index 8b9b06d5b..1ed0c79c8 100644 --- a/plugins/lint-staged/readme.md +++ b/plugins/lint-staged/readme.md @@ -51,12 +51,11 @@ flowchart G --> H[prettier index.js] ``` -## Options + +## Tasks -No options provided. +### `LintStaged` -## Tasks +Run `lint-staged` in your repo, for use with git hooks. -| Task | Description | Preconfigured hooks | -|-|-|-| -| `LintStaged` | run lint-staged on git staged files | `git:precommit` | + From 594ada4c9b99d2e11392d00d6eaef3e1472ecd4d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 09:30:20 +0100 Subject: [PATCH 239/321] build: remove final log from generate-docs --- scripts/generate-docs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index 4ad68e05e..983c12c85 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -117,4 +117,4 @@ async function main() { ) } -main().then(console.log, console.error) +main() From e46b198afa8c72e845c351ae2296ae0129e86542 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 10:22:35 +0100 Subject: [PATCH 240/321] build: explicit support for hiding autogenerated docs in script --- lib/schemas/src/hooks/package-json.ts | 2 +- plugins/package-json-hook/readme.md | 4 ++-- scripts/generate-docs.js | 10 +++++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/schemas/src/hooks/package-json.ts b/lib/schemas/src/hooks/package-json.ts index 8dfdd7e4c..acc4b26a0 100644 --- a/lib/schemas/src/hooks/package-json.ts +++ b/lib/schemas/src/hooks/package-json.ts @@ -44,7 +44,7 @@ will result in the following output in \`package.json\`: } ~~~ - +--> diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index 983c12c85..9038c5226 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -67,10 +67,18 @@ const EMPTY_OBJECT_SCHEMA = `#### Task options _All properties are optional._` function postProcessMarkdown(markdown) { - return markdown + let replaced = markdown .replace(/^#/gm, '##') .replace(/_Object containing the following properties:_\n\n/g, '') .replaceAll(EMPTY_OBJECT_SCHEMA, '') + + // for more complex types, the autogenerated schema docs aren't that readable. + // we can hide them by adding an unclosed HTML commment in the description. + if (replaced.includes('')) { + replaced += '-->\n' + } + + return replaced } const BEGIN_COMMENT = '\n' From b21c266800a18eeda3406bab7ad2feac22b687c9 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 10:40:11 +0100 Subject: [PATCH 241/321] docs(heroku): autogenerate options docs --- lib/schemas/src/plugins/heroku.ts | 12 ++- lib/schemas/src/tasks.ts | 3 + lib/schemas/src/tasks/heroku-production.ts | 29 ++++++- plugins/heroku/readme.md | 90 ++++++++++++++-------- plugins/package-json-hook/readme.md | 3 +- 5 files changed, 100 insertions(+), 37 deletions(-) diff --git a/lib/schemas/src/plugins/heroku.ts b/lib/schemas/src/plugins/heroku.ts index d6e2bc8cd..fdcd995eb 100644 --- a/lib/schemas/src/plugins/heroku.ts +++ b/lib/schemas/src/plugins/heroku.ts @@ -2,8 +2,16 @@ import { PromptGenerators } from '../prompts' import { z } from 'zod' export const HerokuSchema = z.object({ - pipeline: z.string().describe('this can be found at https://dashboard.heroku.com/pipelines/[APP_ID]'), - systemCode: z.string().describe('this can be found at https://biz-ops.in.ft.com/System/[APP_NAME]') + pipeline: z + .string() + .describe( + "the ID of your app's Heroku pipeline. this can be found at https://dashboard.heroku.com/pipelines/[PIPELINE_ID]" + ), + systemCode: z + .string() + .describe( + "your app's Biz Ops system code. this can be found at https://biz-ops.in.ft.com/System/[SYSTEM_CODE]" + ) }) export type HerokuOptions = z.infer diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index e9ddde34a..709ab7406 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -21,6 +21,9 @@ export const TaskSchemas = { Cypress: CypressSchema, Eslint: ESLintSchema, HerokuProduction: HerokuProductionSchema, + HerokuReview: z.object({}).describe('Create and deploy a Heroku review app.'), + HerokuStaging: z.object({}).describe('Deploy to the Heroku staging app.'), + HerokuTeardown: z.object({}).describe("Scale down the Heroku staging app once it's no longer needed."), Jest: JestSchema, LintStaged: z.object({}).describe('Run `lint-staged` in your repo, for use with git hooks.'), Mocha: MochaSchema, diff --git a/lib/schemas/src/tasks/heroku-production.ts b/lib/schemas/src/tasks/heroku-production.ts index fccb575ba..a76541692 100644 --- a/lib/schemas/src/tasks/heroku-production.ts +++ b/lib/schemas/src/tasks/heroku-production.ts @@ -128,7 +128,34 @@ export type HerokuScaling = z.infer export const HerokuProductionSchema = z.object({ scaling: HerokuScalingSchema -}) +}).describe(`Promote the Heroku staging app to production. + +### Task options + +\`scaling\`: an object with scaling configuration for each app and dyno. The first-level keys are the names of your production apps, and the second level keys are names of the dynos within each app (this should usually at least include \`web\`). + +#### Scaling configuration + +| Property | Description | Type | +|-|-|-| +| \`size\` | the [Dyno type](https://devcenter.heroku.com/articles/dyno-types) for this dyno, e.g. \`standard-1x\`. apps in the FT Heroku account can only use [professional tier dynos](https://devcenter.heroku.com/articles/dyno-types#dyno-tiers-and-mixing-dyno-types). | \`string\` | +| \`quantity\` | how many of this dyno to use | \`number\` | + +#### Example + +~~~yml +options: + tasks: + HerokuProduction: + scaling: + ft-next-static-eu: + web: + size: standard-1x + quantity: 1 +~~~ + + +## Tasks -```sh -npx dotcom-tool-kit --install -``` +### `HerokuProduction` -This plugin cannot currently automatically install itself to heroku configuration, so it will exit, and explain what you need to include in the config. +Promote the Heroku staging app to production. -## Options +#### Task options -| Key | Description | Default value | +`scaling`: an object with scaling configuration for each app and dyno. The first-level keys are the names of your production apps, and the second level keys are names of the dynos within each app (this should usually at least include `web`). + +##### Scaling configuration + +| Property | Description | Type | |-|-|-| -| `pipeline` | (required) the pipeline name for your application as it's defined in Heroku | none | -| `systemCode` | (required) system code for your application as it's defined in Biz Ops | none | -| `scaling` | (required) configuration for dyno scaling with a quantity and size for each production app | none | +| `size` | the [Dyno type](https://devcenter.heroku.com/articles/dyno-types) for this dyno, e.g. `standard-1x`. apps in the FT Heroku account can only use [professional tier dynos](https://devcenter.heroku.com/articles/dyno-types#dyno-tiers-and-mixing-dyno-types). | `string` | +| `quantity` | how many of this dyno to use | `number` | -Here's what your configuration might look like passing in the above options: +##### Example -```yml +~~~yml options: - '@dotcom-tool-kit/heroku': - pipeline: 'ft-next-static' - systemCode: 'next-static' - scaling: - ft-next-static-eu: - web: - size: standard-1x - quantity: 1 -``` + tasks: + HerokuProduction: + scaling: + ft-next-static-eu: + web: + size: standard-1x + quantity: 1 +~~~ -## Hooks + + + +## Plugin-wide options + +### `@dotcom-tool-kit/heroku` + +| Property | Description | Type | +| :-------------------- | :-------------------------------------------------------------------------------------------------------------- | :------- | +| **`pipeline`** (\*) | the ID of your app's Heroku pipeline. this can be found at https://dashboard.heroku.com/pipelines/[PIPELINE_ID] | `string` | +| **`systemCode`** (\*) | your app's Biz Ops system code. this can be found at https://biz-ops.in.ft.com/System/[SYSTEM_CODE] | `string` | + +_(\*) Required._ + diff --git a/plugins/package-json-hook/readme.md b/plugins/package-json-hook/readme.md index 3d4903e6f..d63a6e717 100644 --- a/plugins/package-json-hook/readme.md +++ b/plugins/package-json-hook/readme.md @@ -73,4 +73,5 @@ _Object record with dynamic keys:_ - _keys of type_ `string` - _values of type_ _Object with dynamic keys of type_ `string` _and values of type_ `Array | string` _or_ _Object with properties:_
  • `commands`: `Array | string`
  • `trailingString`: `string`
---> +--> + From 1d112ed8aec7fbf50251d4640f28c304f120e4a6 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 10:51:14 +0100 Subject: [PATCH 242/321] build: regenerate package-lock.json based on next --- package-lock.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/package-lock.json b/package-lock.json index 8471dffe3..a2c588a9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1039,8 +1039,12 @@ "core/sandbox": { "version": "1.0.0", "license": "ISC", + "workspaces": [ + "packages/*" + ], "dependencies": { "@dotcom-tool-kit/base": "file:../../lib/base", + "@dotcom-tool-kit/monorepo": "file:../../plugins/monorepo", "@dotcom-tool-kit/node": "file:../../plugins/node", "@dotcom-tool-kit/package-json-hook": "file:../../plugins/package-json-hook", "dotcom-tool-kit": "file:../cli" @@ -6264,6 +6268,10 @@ "resolved": "plugins/mocha", "link": true }, + "node_modules/@dotcom-tool-kit/monorepo": { + "resolved": "plugins/monorepo", + "link": true + }, "node_modules/@dotcom-tool-kit/n-test": { "resolved": "plugins/n-test", "link": true @@ -30608,6 +30616,7 @@ "version": "2.4.1", "license": "0BSD" }, + "plugins/monorepo": {}, "plugins/n-test": { "name": "@dotcom-tool-kit/n-test", "version": "3.3.1", From f60a21c57bcad319ea3e971a37d4cdf0983549c3 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 11:40:11 +0100 Subject: [PATCH 243/321] build: add pre-push hook to regenerate docs --- package.json | 1 + scripts/generate-and-commit-docs.sh | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100755 scripts/generate-and-commit-docs.sh diff --git a/package.json b/package.json index 4a5837dbd..2a6925ba0 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "husky": { "hooks": { "pre-commit": "lint-staged", + "pre-push": "./scripts/generate-and-commit-docs.sh", "commit-msg": "commitlint --edit", "post-checkout": "npm run clean-up-packages -- $HUSKY_GIT_PARAMS" } diff --git a/scripts/generate-and-commit-docs.sh b/scripts/generate-and-commit-docs.sh new file mode 100755 index 000000000..4348e07ee --- /dev/null +++ b/scripts/generate-and-commit-docs.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -euo pipefail + +git stash --staged --quiet + +node ./scripts/generate-docs.js + +if ! git diff --quiet --exit-code; then + git commit -m 'docs: automatically regenerate schema docs' plugins/*/readme.md + + echo '!! automatically generated documentation has been regenerated and committed. please push again' + git stash pop + exit 1 +fi + +git stash pop From f0d74528c3931766ea4964c5d4cb474a88785866 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 11:41:22 +0100 Subject: [PATCH 244/321] docs: minor change to test prepush hook --- lib/schemas/src/tasks/heroku-production.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/schemas/src/tasks/heroku-production.ts b/lib/schemas/src/tasks/heroku-production.ts index a76541692..3fb968c49 100644 --- a/lib/schemas/src/tasks/heroku-production.ts +++ b/lib/schemas/src/tasks/heroku-production.ts @@ -154,6 +154,7 @@ options: quantity: 1 ~~~ + `) export type PackageJsonOptions = z.infer diff --git a/lib/schemas/src/tasks/heroku-production.ts b/lib/schemas/src/tasks/heroku-production.ts index 3fb968c49..1f6f0913a 100644 --- a/lib/schemas/src/tasks/heroku-production.ts +++ b/lib/schemas/src/tasks/heroku-production.ts @@ -154,8 +154,7 @@ options: quantity: 1 ~~~ - - `) export const generators: PromptGenerators = { diff --git a/plugins/heroku/readme.md b/plugins/heroku/readme.md index ce342cdbf..9dbac5ec2 100644 --- a/plugins/heroku/readme.md +++ b/plugins/heroku/readme.md @@ -50,33 +50,21 @@ options: quantity: 1 ~~~ + - - ## Plugin-wide options diff --git a/plugins/lint-staged/readme.md b/plugins/lint-staged/readme.md index 1ed0c79c8..8df31aaec 100644 --- a/plugins/lint-staged/readme.md +++ b/plugins/lint-staged/readme.md @@ -57,5 +57,4 @@ flowchart ### `LintStaged` Run `lint-staged` in your repo, for use with git hooks. - diff --git a/plugins/npm/readme.md b/plugins/npm/readme.md index 3a59e6eec..04679f5a9 100644 --- a/plugins/npm/readme.md +++ b/plugins/npm/readme.md @@ -26,9 +26,7 @@ plugins: Prune development npm dependencies. - ### `NpmPublish` Publish package to the npm registry. - diff --git a/plugins/package-json-hook/readme.md b/plugins/package-json-hook/readme.md index d63a6e717..42c4a619e 100644 --- a/plugins/package-json-hook/readme.md +++ b/plugins/package-json-hook/readme.md @@ -65,13 +65,6 @@ will result in the following output in `package.json`: } ~~~ - -#### Hook options - -_Object record with dynamic keys:_ - -- _keys of type_ `string` -- _values of type_ _Object with dynamic keys of type_ `string` _and values of type_ `Array | string` _or_ _Object with properties:_
  • `commands`: `Array | string`
  • `trailingString`: `string`
---> diff --git a/scripts/generate-docs.js b/scripts/generate-docs.js index 9038c5226..356727a38 100644 --- a/scripts/generate-docs.js +++ b/scripts/generate-docs.js @@ -9,7 +9,18 @@ const fs = require('fs/promises') const { convertSchemas, formatModelsAsMarkdown } = require('zod2md') function formatSchemas(title, schemas) { - const converted = convertSchemas(schemas) + const converted = schemas.flatMap((schema) => { + const converted = convertSchemas([schema]) + + // for more complex types, the autogenerated schema docs aren't that readable. + // we can hide them by adding this HTML commment in the description. + if (converted[0]?.description?.includes('')) { + converted[0].type = undefined + } + + return converted + }) + return postProcessMarkdown( formatModelsAsMarkdown(converted, { title, transformName: (name) => '`' + name + '`' }) ) @@ -59,26 +70,23 @@ async function formatPluginSchemas(plugin) { ` } -const EMPTY_OBJECT_SCHEMA = `#### Task options +const schemasToRemove = () => + new RegExp( + `#### (Task|Hook) options -| Property | Type | -| :------- | :--- | +(\\| Property \\| Type \\| +\\| :------- \\| :--- \\| -_All properties are optional._` +_All properties are optional._|undefined) +`, + 'g' + ) function postProcessMarkdown(markdown) { - let replaced = markdown + return markdown .replace(/^#/gm, '##') .replace(/_Object containing the following properties:_\n\n/g, '') - .replaceAll(EMPTY_OBJECT_SCHEMA, '') - - // for more complex types, the autogenerated schema docs aren't that readable. - // we can hide them by adding an unclosed HTML commment in the description. - if (replaced.includes('')) { - replaced += '-->\n' - } - - return replaced + .replaceAll(schemasToRemove(), '') } const BEGIN_COMMENT = '\n' From ad5d276de71c91b333078834790e41124dbfa7ac Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 13:07:07 +0100 Subject: [PATCH 255/321] build: make sure compiled typescript is up to date when generating docs on prepush --- scripts/generate-and-commit-docs.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/generate-and-commit-docs.sh b/scripts/generate-and-commit-docs.sh index 2b22a4ae8..040446e57 100755 --- a/scripts/generate-and-commit-docs.sh +++ b/scripts/generate-and-commit-docs.sh @@ -12,6 +12,7 @@ if [ "$HAS_CHANGES" == "yes" ]; then git stash --staged --quiet fi +npm run build node ./scripts/generate-docs.js if ! git diff --quiet --exit-code; then From c216b34022c5ecb1b6c858d06761f699edd284d3 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 13:18:17 +0100 Subject: [PATCH 256/321] docs(serverless): document remaining tasks --- lib/schemas/src/tasks.ts | 3 +++ plugins/serverless/.toolkitrc.yml | 1 + plugins/serverless/readme.md | 12 ++++++++++++ 3 files changed, 16 insertions(+) diff --git a/lib/schemas/src/tasks.ts b/lib/schemas/src/tasks.ts index 709ab7406..80b20ba62 100644 --- a/lib/schemas/src/tasks.ts +++ b/lib/schemas/src/tasks.ts @@ -34,7 +34,10 @@ export const TaskSchemas = { NTest: SmokeTestSchema, Pa11y: Pa11ySchema, Prettier: PrettierSchema, + ServerlessDeploy: z.object({}).describe('Deploy a serverless function'), + ServerlessProvision: z.object({}).describe('Provision a review serverless function'), ServerlessRun: ServerlessRunSchema, + ServerlessTeardown: z.object({}).describe('Tear down existing serverless functions'), TypeScript: TypeScriptSchema, UploadAssetsToS3: UploadAssetsToS3Schema, Webpack: WebpackSchema diff --git a/plugins/serverless/.toolkitrc.yml b/plugins/serverless/.toolkitrc.yml index 4dc4621b9..76dd06300 100644 --- a/plugins/serverless/.toolkitrc.yml +++ b/plugins/serverless/.toolkitrc.yml @@ -2,5 +2,6 @@ tasks: ServerlessRun: './lib/tasks/run' ServerlessDeploy: './lib/tasks/deploy' ServerlessProvision: './lib/tasks/provision' + ServerlessTeardown: './lib/tasks/teardown' version: 2 diff --git a/plugins/serverless/readme.md b/plugins/serverless/readme.md index 0d1d53384..c7617e53f 100644 --- a/plugins/serverless/readme.md +++ b/plugins/serverless/readme.md @@ -34,6 +34,18 @@ Run serverless functions locally _All properties are optional._ +### `ServerlessDeploy` + +Deploy a serverless function + +### `ServerlessProvision` + +Provision a review serverless function + +### `ServerlessTeardown` + +Tear down existing serverless functions + ## Plugin-wide options From 81629cc6f055f7d248ea98ba648d0c7895be0bb1 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 13:20:56 +0100 Subject: [PATCH 257/321] chore: remove now-unused description field from task and hook --- lib/base/src/hook.ts | 1 - lib/base/src/task.ts | 2 -- plugins/babel/src/tasks/babel.ts | 2 -- plugins/eslint/src/tasks/eslint.ts | 2 -- plugins/heroku/src/tasks/production.ts | 2 -- plugins/heroku/src/tasks/review.ts | 2 -- plugins/heroku/src/tasks/staging.ts | 2 -- plugins/heroku/src/tasks/teardown.ts | 2 -- plugins/jest/src/tasks/jest.ts | 2 -- plugins/mocha/src/tasks/mocha.ts | 2 -- plugins/n-test/src/tasks/n-test.ts | 2 -- plugins/next-router/src/tasks/next-router.ts | 2 -- plugins/node/src/tasks/node.ts | 2 -- plugins/nodemon/src/tasks/nodemon.ts | 2 -- plugins/npm/src/tasks/prune.ts | 2 -- plugins/npm/src/tasks/publish.ts | 2 -- plugins/pa11y/src/tasks/pa11y.ts | 2 -- plugins/prettier/src/tasks/prettier.ts | 2 -- plugins/serverless/src/tasks/deploy.ts | 2 -- plugins/serverless/src/tasks/provision.ts | 2 -- plugins/serverless/src/tasks/run.ts | 2 -- plugins/serverless/src/tasks/teardown.ts | 2 -- plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts | 2 -- plugins/webpack/src/tasks/webpack.ts | 2 -- 24 files changed, 47 deletions(-) diff --git a/lib/base/src/hook.ts b/lib/base/src/hook.ts index e862493a2..9fb815b08 100644 --- a/lib/base/src/hook.ts +++ b/lib/base/src/hook.ts @@ -14,7 +14,6 @@ export interface HookInstallation> { export abstract class Hook extends Base { logger: Logger - static description?: string // This field is used to collect hooks that share state when running their // install methods. All hooks in the same group will run their install method // one after the other, and then their commitInstall method will be run with diff --git a/lib/base/src/task.ts b/lib/base/src/task.ts index a8ba1763c..7b0f35f68 100644 --- a/lib/base/src/task.ts +++ b/lib/base/src/task.ts @@ -11,8 +11,6 @@ export abstract class Task< task?: z.ZodTypeAny } = Record > extends Base { - static description: string - static get [typeSymbol](): symbol { return taskSymbol } diff --git a/plugins/babel/src/tasks/babel.ts b/plugins/babel/src/tasks/babel.ts index 207eb2065..5c7427c1c 100644 --- a/plugins/babel/src/tasks/babel.ts +++ b/plugins/babel/src/tasks/babel.ts @@ -10,8 +10,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import { hookConsole } from '@dotcom-tool-kit/logger' export default class Babel extends Task<{ task: typeof BabelSchema }> { - static description = 'build babel' - async run(): Promise { const fileGlob = this.options.files const files = await fg(fileGlob) diff --git a/plugins/eslint/src/tasks/eslint.ts b/plugins/eslint/src/tasks/eslint.ts index c2fb06cac..005b3663d 100644 --- a/plugins/eslint/src/tasks/eslint.ts +++ b/plugins/eslint/src/tasks/eslint.ts @@ -5,8 +5,6 @@ import { ESLintSchema } from '@dotcom-tool-kit/schemas/lib/tasks/eslint' import { ESLint } from 'eslint' export default class Eslint extends Task<{ task: typeof ESLintSchema }> { - static description = '' - async run(files?: string[]): Promise { const eslint = new ESLint({ overrideConfigFile: this.options.configPath }) const results = await eslint.lintFiles(files ?? this.options.files) diff --git a/plugins/heroku/src/tasks/production.ts b/plugins/heroku/src/tasks/production.ts index feb7b61f4..dbd446a44 100644 --- a/plugins/heroku/src/tasks/production.ts +++ b/plugins/heroku/src/tasks/production.ts @@ -13,8 +13,6 @@ export default class HerokuProduction extends Task<{ plugin: typeof HerokuSchema task: typeof HerokuProductionSchema }> { - static description = '' - async run(): Promise { try { this.logger.verbose('retrieving staging slug...') diff --git a/plugins/heroku/src/tasks/review.ts b/plugins/heroku/src/tasks/review.ts index 735ef1f4b..faa4127dc 100644 --- a/plugins/heroku/src/tasks/review.ts +++ b/plugins/heroku/src/tasks/review.ts @@ -10,8 +10,6 @@ import herokuClient, { extractHerokuError } from '../herokuClient' import type { HerokuApiResPipeline } from 'heroku-client' export default class HerokuReview extends Task<{ plugin: typeof HerokuSchema }> { - static description = '' - async run(): Promise { try { const pipeline = await herokuClient diff --git a/plugins/heroku/src/tasks/staging.ts b/plugins/heroku/src/tasks/staging.ts index daa194ccc..77b6c026c 100644 --- a/plugins/heroku/src/tasks/staging.ts +++ b/plugins/heroku/src/tasks/staging.ts @@ -11,8 +11,6 @@ import { HerokuSchema } from '@dotcom-tool-kit/schemas/lib/plugins/heroku' import { setStagingSlug } from '../setStagingSlug' export default class HerokuStaging extends Task<{ plugin: typeof HerokuSchema }> { - static description = '' - async run(): Promise { try { this.logger.verbose(`retrieving pipeline details...`) diff --git a/plugins/heroku/src/tasks/teardown.ts b/plugins/heroku/src/tasks/teardown.ts index 695f86ed8..8e6920c18 100644 --- a/plugins/heroku/src/tasks/teardown.ts +++ b/plugins/heroku/src/tasks/teardown.ts @@ -5,8 +5,6 @@ import { scaleDyno } from '../scaleDyno' import { ToolKitError } from '@dotcom-tool-kit/error' export default class HerokuTeardown extends Task { - static description = '' - async run(): Promise { //scale down staging const state = readState('staging') diff --git a/plugins/jest/src/tasks/jest.ts b/plugins/jest/src/tasks/jest.ts index e9040c7a5..c9f91d5cb 100644 --- a/plugins/jest/src/tasks/jest.ts +++ b/plugins/jest/src/tasks/jest.ts @@ -30,8 +30,6 @@ async function guessVCpus(): Promise { } export default class Jest extends Task<{ task: typeof JestSchema }> { - static description = '' - async run(): Promise { const args = ['--colors', this.options.configPath ? `--config=${this.options.configPath}` : ''] diff --git a/plugins/mocha/src/tasks/mocha.ts b/plugins/mocha/src/tasks/mocha.ts index 12c4d1ba9..31bf84139 100644 --- a/plugins/mocha/src/tasks/mocha.ts +++ b/plugins/mocha/src/tasks/mocha.ts @@ -7,8 +7,6 @@ import { promisify } from 'util' const mochaCLIPath = require.resolve('mocha/bin/mocha') export default class Mocha extends Task<{ task: typeof MochaSchema }> { - static description = '' - async run(): Promise { const files = await promisify(glob)(this.options.files) diff --git a/plugins/n-test/src/tasks/n-test.ts b/plugins/n-test/src/tasks/n-test.ts index 5235390dc..f9569c274 100644 --- a/plugins/n-test/src/tasks/n-test.ts +++ b/plugins/n-test/src/tasks/n-test.ts @@ -5,8 +5,6 @@ import { SmokeTest } from '@financial-times/n-test' import { readState } from '@dotcom-tool-kit/state' export default class NTest extends Task<{ task: typeof SmokeTestSchema }> { - static description = '' - async run(): Promise { const appState = readState('review') ?? readState('staging') diff --git a/plugins/next-router/src/tasks/next-router.ts b/plugins/next-router/src/tasks/next-router.ts index e0391d33a..d5f7764bf 100644 --- a/plugins/next-router/src/tasks/next-router.ts +++ b/plugins/next-router/src/tasks/next-router.ts @@ -8,8 +8,6 @@ import { fork } from 'child_process' import { NextRouterSchema } from '@dotcom-tool-kit/schemas/lib/plugins/next-router' export default class NextRouter extends Task<{ plugin: typeof NextRouterSchema }> { - static description = '' - async run(): Promise { const doppler = new DopplerEnvVars(this.logger, 'dev', { project: 'next-router' diff --git a/plugins/node/src/tasks/node.ts b/plugins/node/src/tasks/node.ts index 4a1e1621c..19ab57c25 100644 --- a/plugins/node/src/tasks/node.ts +++ b/plugins/node/src/tasks/node.ts @@ -8,8 +8,6 @@ import getPort from 'get-port' import waitPort from 'wait-port' export default class Node extends Task<{ task: typeof NodeSchema }> { - static description = '' - async run(): Promise { const { entry, args, useDoppler, ports } = this.options diff --git a/plugins/nodemon/src/tasks/nodemon.ts b/plugins/nodemon/src/tasks/nodemon.ts index 7f97fd1c2..66f459c31 100644 --- a/plugins/nodemon/src/tasks/nodemon.ts +++ b/plugins/nodemon/src/tasks/nodemon.ts @@ -9,8 +9,6 @@ import { Readable } from 'stream' import { shouldDisableNativeFetch } from 'dotcom-tool-kit' export default class Nodemon extends Task<{ task: typeof NodemonSchema }> { - static description = '' - async run(): Promise { const { entry, configPath, useDoppler, ports } = this.options diff --git a/plugins/npm/src/tasks/prune.ts b/plugins/npm/src/tasks/prune.ts index 46cb52a47..a821f7aa0 100644 --- a/plugins/npm/src/tasks/prune.ts +++ b/plugins/npm/src/tasks/prune.ts @@ -3,8 +3,6 @@ import { ToolKitError } from '@dotcom-tool-kit/error' import * as exec from '@actions/exec' export default class NpmPrune extends Task { - static description = '' - async run(): Promise { try { this.logger.verbose('pruning dev dependencies...') diff --git a/plugins/npm/src/tasks/publish.ts b/plugins/npm/src/tasks/publish.ts index 3c33ed282..3813b2414 100644 --- a/plugins/npm/src/tasks/publish.ts +++ b/plugins/npm/src/tasks/publish.ts @@ -17,8 +17,6 @@ const prereleaseRegex = /^v\d+\.\d+\.\d+(?:-\w+\.\d+)$/ const releaseRegex = /^v\d+\.\d+\.\d+$/ export default class NpmPublish extends Task { - static description = '' - getNpmTag(tag: string): TagType { if (!tag) { throw new ToolKitError( diff --git a/plugins/pa11y/src/tasks/pa11y.ts b/plugins/pa11y/src/tasks/pa11y.ts index 536c33cf7..1b13e81a9 100644 --- a/plugins/pa11y/src/tasks/pa11y.ts +++ b/plugins/pa11y/src/tasks/pa11y.ts @@ -7,8 +7,6 @@ import { readState } from '@dotcom-tool-kit/state' const pa11yCIPath = require.resolve('pa11y-ci/bin/pa11y-ci') export default class Pa11y extends Task<{ task: typeof Pa11ySchema }> { - static description = '' - async run(): Promise { const localState = readState('local') const reviewState = readState('review') diff --git a/plugins/prettier/src/tasks/prettier.ts b/plugins/prettier/src/tasks/prettier.ts index fa8953222..c967b1355 100644 --- a/plugins/prettier/src/tasks/prettier.ts +++ b/plugins/prettier/src/tasks/prettier.ts @@ -7,8 +7,6 @@ import { Task } from '@dotcom-tool-kit/base' import { ToolKitError } from '@dotcom-tool-kit/error' export default class Prettier extends Task<{ task: typeof PrettierSchema }> { - static description = '' - async run(files?: string[]): Promise { try { const filepaths = await fg(files ?? this.options.files) diff --git a/plugins/serverless/src/tasks/deploy.ts b/plugins/serverless/src/tasks/deploy.ts index 54cfb2c33..8e31575c1 100644 --- a/plugins/serverless/src/tasks/deploy.ts +++ b/plugins/serverless/src/tasks/deploy.ts @@ -4,8 +4,6 @@ import { ServerlessSchema } from '@dotcom-tool-kit/schemas/lib/plugins/serverles import { spawn } from 'child_process' export default class ServerlessDeploy extends Task<{ plugin: typeof ServerlessSchema }> { - static description = 'Deploys on AWS' - async run(): Promise { const { configPath, regions, systemCode } = this.pluginOptions diff --git a/plugins/serverless/src/tasks/provision.ts b/plugins/serverless/src/tasks/provision.ts index fc8634ca1..c0a7f466a 100644 --- a/plugins/serverless/src/tasks/provision.ts +++ b/plugins/serverless/src/tasks/provision.ts @@ -6,8 +6,6 @@ import { spawn } from 'child_process' import { readState, writeState } from '@dotcom-tool-kit/state' export default class ServerlessProvision extends Task<{ plugin: typeof ServerlessSchema }> { - static description = 'Provisions a job on AWS' - async run(): Promise { const { configPath, systemCode, regions } = this.pluginOptions const ciState = readState('ci') diff --git a/plugins/serverless/src/tasks/run.ts b/plugins/serverless/src/tasks/run.ts index df45b5b59..23de8c817 100644 --- a/plugins/serverless/src/tasks/run.ts +++ b/plugins/serverless/src/tasks/run.ts @@ -11,8 +11,6 @@ export default class ServerlessRun extends Task<{ task: typeof ServerlessRunSchema plugin: typeof ServerlessSchema }> { - static description = 'Run serverless functions locally' - async run(): Promise { const { useDoppler, ports } = this.options const { configPath } = this.pluginOptions diff --git a/plugins/serverless/src/tasks/teardown.ts b/plugins/serverless/src/tasks/teardown.ts index 987a7c944..94217a044 100644 --- a/plugins/serverless/src/tasks/teardown.ts +++ b/plugins/serverless/src/tasks/teardown.ts @@ -6,8 +6,6 @@ import { readState } from '@dotcom-tool-kit/state' import { spawn } from 'child_process' export default class ServerlessTeardown extends Task<{ plugin: typeof ServerlessSchema }> { - static description = 'Teardown existing serverless functions' - async run(): Promise { const { configPath, regions, systemCode } = this.pluginOptions diff --git a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts index 719a19173..ddfe5e419 100644 --- a/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts +++ b/plugins/upload-assets-to-s3/src/tasks/upload-assets-to-s3.ts @@ -12,8 +12,6 @@ import { } from '@dotcom-tool-kit/schemas/lib/tasks/upload-assets-to-s3' export default class UploadAssetsToS3 extends Task<{ task: typeof UploadAssetsToS3Schema }> { - static description = '' - async run(): Promise { await this.uploadAssetsToS3(this.options) } diff --git a/plugins/webpack/src/tasks/webpack.ts b/plugins/webpack/src/tasks/webpack.ts index 57c5d646b..130454799 100644 --- a/plugins/webpack/src/tasks/webpack.ts +++ b/plugins/webpack/src/tasks/webpack.ts @@ -6,8 +6,6 @@ import { fork } from 'child_process' const webpackCLIPath = require.resolve('webpack-cli/bin/cli') export default class Webpack extends Task<{ task: typeof WebpackSchema }> { - static description = 'build webpack' - async run(): Promise { this.logger.info('starting Webpack...') const args = ['build', '--color', `--mode=${this.options.envName}`] From aa2a27f0978d176f693b5e57899f0089bfeb1b1d Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 13:22:16 +0100 Subject: [PATCH 258/321] chore: regenerated package-lock.json again --- package-lock.json | 4121 ++++++++++++++++++++++++++++++--------------- 1 file changed, 2754 insertions(+), 1367 deletions(-) diff --git a/package-lock.json b/package-lock.json index d3386fa41..0dd70056d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,8 +102,9 @@ }, "core/cli/node_modules/@types/node": { "version": "17.0.45", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "dev": true }, "core/cli/node_modules/globby": { "version": "10.0.2", @@ -125,7 +126,8 @@ }, "core/cli/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "core/cli/node_modules/yaml": { "version": "2.4.1", @@ -140,7 +142,8 @@ }, "core/cli/node_modules/zod-validation-error": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-2.1.0.tgz", + "integrity": "sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==", "engines": { "node": ">=18.0.0" }, @@ -196,7 +199,8 @@ }, "core/create/node_modules/@aws-sdk/abort-controller": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.296.0.tgz", + "integrity": "sha512-gNUFBlBw6+sEMfDjPVa83iscpQwXBS4uoiZXnfeQ6s6tnaxqQpJDrBBmNvYqDEXNdaAJX4FhayEwkSvtir/f3A==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -207,7 +211,8 @@ }, "core/create/node_modules/@aws-sdk/client-sso": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.301.0.tgz", + "integrity": "sha512-nABoNn0O79PL72jg2oy9gR/MLmM4opZ6nQefXvXUb6RzlITZCCZ6uKkGcH2LMxOcRu6qQlY+uauX+9p0GJexlg==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -248,7 +253,8 @@ }, "core/create/node_modules/@aws-sdk/client-sso-oidc": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.301.0.tgz", + "integrity": "sha512-bCBA70/7gkrk1s1iGWt3st4p9yNIkQ3e+KV8Kx3uzRvjD0f7KltGqSNA28453tsa7ko+H/V4c7fzrJnWaQomCg==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -289,7 +295,8 @@ }, "core/create/node_modules/@aws-sdk/client-sts": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.301.0.tgz", + "integrity": "sha512-OS8wE21Lxd8aT8PMj/dusCUZKXmXaxnSI4RIO3M8w/ZPRMKkBHtzB+JXbzUcpGGxvt9mse8l6w9iLIE6XuHmig==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -334,7 +341,8 @@ }, "core/create/node_modules/@aws-sdk/config-resolver": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.300.0.tgz", + "integrity": "sha512-u3YS+XWjoHmH9wh07Lv+HueYZek/wTO8tlGvVzrlACpaS1JrALuCw8UsJUHNDack63xh9v4oMf+7c0kjuqbmtA==", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-config-provider": "3.295.0", @@ -347,7 +355,8 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-env": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.296.0.tgz", + "integrity": "sha512-eDWSU3p04gytkkVXnYn05YzrP5SEaj/DQiafd4y+iBl8IFfF3zM6982rs6qFhvpwrHeSbLqHNfKR1HDWVwfG5g==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -359,7 +368,8 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-imds": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.300.0.tgz", + "integrity": "sha512-l7ZFGlr4TjhS0FIt3XwuAJYNAbQ4eDsovMMUVYLDPti1NxlbQDH85xAyaDWF9dU1Gulrpfzz9Ei7q4GYFFPHnQ==", "dependencies": { "@aws-sdk/node-config-provider": "3.300.0", "@aws-sdk/property-provider": "3.296.0", @@ -373,7 +383,8 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-ini": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.301.0.tgz", + "integrity": "sha512-tAsNH6vQZ7U459FzjStIXoi3HZAsl6y8CMf6364dyisZ0xiCiVHLxziTmSxntcR0560NFFSOY1WS5MrbIIneGQ==", "dependencies": { "@aws-sdk/credential-provider-env": "3.296.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -391,7 +402,8 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-node": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.301.0.tgz", + "integrity": "sha512-WNz7+HoGEkAHaOL1d4D2c/LxYS3zBdqzLs7uYgekoqTSMQhTaIMyJIJgChcklAmV/yM1+2c3lS1NEtCCz3/Vxw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.296.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -410,7 +422,8 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-process": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.300.0.tgz", + "integrity": "sha512-HGBLXupPU2XTvHmlcbSgH/zLyhQ1joLIBAvKvyxyjQTIeFSDOufDqRBY4CzNzPv0yJlvSi3gAfL36CR9dh2R4w==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/shared-ini-file-loader": "3.300.0", @@ -423,7 +436,8 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-sso": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.301.0.tgz", + "integrity": "sha512-5mGoBX5WmZRuL3RIWgdhMbnKYHSmM54qEFjbtRiFXZQ1QSItom1ICBCyIEoNMZQ20+iRxyTgf/fGCJrXhDlIqQ==", "dependencies": { "@aws-sdk/client-sso": "3.301.0", "@aws-sdk/property-provider": "3.296.0", @@ -438,7 +452,8 @@ }, "core/create/node_modules/@aws-sdk/credential-provider-web-identity": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.296.0.tgz", + "integrity": "sha512-Rl6Ohoekxe+pccA55XXQDW5wApbg3rGWr6FkmPRcg7Ld6Vfe+HL8OtfsFf83/0eoFerevbif+00BdknXWT05LA==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -450,7 +465,8 @@ }, "core/create/node_modules/@aws-sdk/fetch-http-handler": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.296.0.tgz", + "integrity": "sha512-wHuKQ+PGKQkYGVuIGscbcbbASl8yIVOSC+QTrZQ4PNsMDvQd9ey2npsmxZk1Z2ULaxY+qYtZCmByyGc8k51TtQ==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/querystring-builder": "3.296.0", @@ -461,7 +477,8 @@ }, "core/create/node_modules/@aws-sdk/hash-node": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.296.0.tgz", + "integrity": "sha512-01Sgxm0NE3rtEznLY8vx1bfNsIeM5Sk5SjY9RXqnvCf9EyaKH9x5FMS/DX/SgDdIYi3aXbTwiwScNVCNBzOIQA==", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-buffer-from": "3.295.0", @@ -474,7 +491,8 @@ }, "core/create/node_modules/@aws-sdk/invalid-dependency": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.296.0.tgz", + "integrity": "sha512-dmy4fUds0woHGjxwziaSYCLtb/SOfoEeQjW0GFvHj+YGFyY5hJzna4C759Tt8X5obh1evUXlQcH+FL7TS+7tRQ==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -482,7 +500,8 @@ }, "core/create/node_modules/@aws-sdk/is-array-buffer": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.295.0.tgz", + "integrity": "sha512-SCIt10cr5dud7hvwveU4wkLjvkGssJ3GrcbHCds2NwI+JHmpcaaNYLAqi305JAuT29T36U5ssTFDSmrrEOcfag==", "dependencies": { "tslib": "^2.5.0" }, @@ -492,7 +511,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-content-length": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.296.0.tgz", + "integrity": "sha512-e7lJm3kkC2pWZdIw23gpMUk1GrpRTBRqhdFfVwyduXw6Wo4nBYv8Z5MOYy3/SlpjE1BDCaPBoZ3O19cO3arHxg==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -504,7 +524,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-endpoint": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.299.0.tgz", + "integrity": "sha512-37BGxHem6yKjSC6zG2xPjvjE7APIDIvwkxL+/K1Jz9+T6AZITcs7tx5y6mIfvaHsdPuCKjrl7Wzg/9jgUKuLkw==", "dependencies": { "@aws-sdk/middleware-serde": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -518,7 +539,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-host-header": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.296.0.tgz", + "integrity": "sha512-V47dFtfkX5lXWv9GDp71gZVCRws4fEdQ9QF9BQ/2UMSNrYjQLg6mFe7NibH+IJoNOid2FIwWIl94Eos636VGYQ==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -530,7 +552,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-logger": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.296.0.tgz", + "integrity": "sha512-LzfEEFyBR9LXdWwLdtBrmi1vLdzgdJNntEgzqktVF8LwaCyY+9xIE6TGu/2V+9fJHAwECxjOC1eQbNQdAZ0Tmw==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -541,7 +564,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-recursion-detection": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.296.0.tgz", + "integrity": "sha512-UG7TLDPz9ImQG0uVklHTxE9Us7rTImwN+6el6qZCpoTBuGeXgOkfb0/p8izJyFgY/hMUR4cZqs7IdCDUkxQF3w==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -553,7 +577,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-retry": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.300.0.tgz", + "integrity": "sha512-c3tj0Uc64mqnsosAjRBQbit0EUOd0OKrqC5eDB3YCJyLWQSlYRBk4ZBBbN2qTfo3ZCDP+tHgWxRduQlV6Knezg==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/service-error-classification": "3.296.0", @@ -569,7 +594,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-sdk-sts": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.299.0.tgz", + "integrity": "sha512-yE7IiMQpF1FYqLSYOei4AYM9z62ayFfMMyhKE9IFs+TVaag97uz8NaRlr88HDTcBCZ0CMl6UwNJlZytPD4NjCw==", "dependencies": { "@aws-sdk/middleware-signing": "3.299.0", "@aws-sdk/types": "3.296.0", @@ -581,7 +607,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-serde": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.296.0.tgz", + "integrity": "sha512-xk2PpWAAX758oUTGkGBAncpOr7ddIXisjD2Y2r9DDXuE4JMho2x6zcrVSiYsGIQ6MHZ9XNJKBVDiK9PA4iQWGQ==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -592,7 +619,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-signing": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.299.0.tgz", + "integrity": "sha512-anhrjeNuo0470QodEmzteFMnqABNebL900yhfODySXCMiaoeTBpo8Qd8t4q4O8PizA7FeLYA3l/5tb/udp7qew==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/protocol-http": "3.296.0", @@ -607,7 +635,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-stack": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.296.0.tgz", + "integrity": "sha512-Rgo7/mdk9tt4qa9+pzG3AoGNhuj7NmnF5H+3DoPm75h58BYP8hKbKobdPGgI2rZLPtO3PGgmyw/4K4tQJPIZ8g==", "dependencies": { "tslib": "^2.5.0" }, @@ -617,7 +646,8 @@ }, "core/create/node_modules/@aws-sdk/middleware-user-agent": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.299.0.tgz", + "integrity": "sha512-Brm5UcbRhuVVmmbpDN8/WSJPCHogV64jGXL5upfL+iJ0c5eZ57LXOZ8kz++t3BU1rEkSIXHJanneEmn7Wbd5sA==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -630,7 +660,8 @@ }, "core/create/node_modules/@aws-sdk/node-config-provider": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.300.0.tgz", + "integrity": "sha512-60XJV+eW1FyyRNT75kAGdqDHLpWWqnZeCrEyufqQ3BXhhbD1l6oHy5W573DccEO84/0gQYlNbKL8hd8+iB59vA==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/shared-ini-file-loader": "3.300.0", @@ -643,7 +674,8 @@ }, "core/create/node_modules/@aws-sdk/node-http-handler": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.296.0.tgz", + "integrity": "sha512-D15jjPqYSNhEq58BwkmIpD3VwqG4bL5acAaNu5wWAI4S4236JlG+nmpi3gEeE25z1KCwtBl7G30fVRgXYJ2CWA==", "dependencies": { "@aws-sdk/abort-controller": "3.296.0", "@aws-sdk/protocol-http": "3.296.0", @@ -657,7 +689,8 @@ }, "core/create/node_modules/@aws-sdk/property-provider": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.296.0.tgz", + "integrity": "sha512-kjczxE9Od5LoAKQOmxVWISJ9oPG3aCsB+2+NdI+k9EJFDXUUdMcVV3Skei5uHGgKLMsI6CZy8ezZx6YxOSLSew==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -668,7 +701,8 @@ }, "core/create/node_modules/@aws-sdk/protocol-http": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.296.0.tgz", + "integrity": "sha512-0U1Z/+tpwdRiSToWo1bpdkbTzjbLugTnd02ATjvK4B7zi363SUGlKfoWgV+v7FU/22CIUI1ZIe7XzXvq5rJfjA==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -679,7 +713,8 @@ }, "core/create/node_modules/@aws-sdk/querystring-builder": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.296.0.tgz", + "integrity": "sha512-+ZrZdTRaVI1R1xKQNrTwuiRoPateUaJ/DNw/myJpTPt+ZRg0H7LKBGaJYwL4pl5l/z1UM/E1fOttSfSW7GHxfw==", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-uri-escape": "3.295.0", @@ -691,7 +726,8 @@ }, "core/create/node_modules/@aws-sdk/querystring-parser": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.296.0.tgz", + "integrity": "sha512-nLNZKVQfK42euv7101cE5qfg17YCtGcfccx3B5XSAzvyTROR46kwYqbEvYSsWisbZoRhbQc905gB/5E0U5HDIw==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -702,14 +738,16 @@ }, "core/create/node_modules/@aws-sdk/service-error-classification": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.296.0.tgz", + "integrity": "sha512-YIsWSQ38e1+FqXz3CMrkKS0JD8OLlHf6I72PJhbfegePpQQFqi9R8OREjP5V7UR9Z972yruv4i96ROH6SCtmoA==", "engines": { "node": ">=14.0.0" } }, "core/create/node_modules/@aws-sdk/shared-ini-file-loader": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.300.0.tgz", + "integrity": "sha512-xA+V08AMsb1EcNJ2UF896T4I3f6Q/H56Z3gTwcXyFXsCY3lYkEB2MEdST+x4+20emELkYjtu5SNsGgUCBehR7g==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -720,7 +758,8 @@ }, "core/create/node_modules/@aws-sdk/signature-v4": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.299.0.tgz", + "integrity": "sha512-3TtP+S3Tu0Q2/EwJLnN+IEok9nRyez79f6vprqXbC9Lex623cqh/OOYSy2oUjFlIgsIOLPum87/1bfcznYW+yQ==", "dependencies": { "@aws-sdk/is-array-buffer": "3.295.0", "@aws-sdk/types": "3.296.0", @@ -736,7 +775,8 @@ }, "core/create/node_modules/@aws-sdk/smithy-client": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.296.0.tgz", + "integrity": "sha512-HEpsLNozGe9XOWouq5A1TFw5KhFodi8tZqYVNEbSpLoRR+EQKf6OCRvKIRkOn7FnnaOasOR1n7S0D51UG6/irw==", "dependencies": { "@aws-sdk/middleware-stack": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -748,7 +788,8 @@ }, "core/create/node_modules/@aws-sdk/token-providers": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.301.0.tgz", + "integrity": "sha512-TgchzkIOLGMhL3dFKGHyztZ4/HOM/WvJC0bRxvrWTs+iDHRaaKNpzW1RzCVCtbH8F/B9h5qPdRFJ6jTHtCKf4A==", "dependencies": { "@aws-sdk/client-sso-oidc": "3.301.0", "@aws-sdk/property-provider": "3.296.0", @@ -762,7 +803,8 @@ }, "core/create/node_modules/@aws-sdk/types": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.296.0.tgz", + "integrity": "sha512-s0wIac64rrMEo2ioUxP9IarGiiCGmelCspNcoNTPSjGl25QqjhyfQqTeGgS58qJ4fHoQb07qra39930xp1IzJg==", "dependencies": { "tslib": "^2.5.0" }, @@ -772,7 +814,8 @@ }, "core/create/node_modules/@aws-sdk/url-parser": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.296.0.tgz", + "integrity": "sha512-nBgeGF+ziuDSLz+y8UAl6zL2tXxDwh3wqeXFe9ZcR4YW71BWuh+vEqEsaEMutOrfnJacCrYKTs9TkIOW41cEGg==", "dependencies": { "@aws-sdk/querystring-parser": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -781,7 +824,8 @@ }, "core/create/node_modules/@aws-sdk/util-base64": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.295.0.tgz", + "integrity": "sha512-z1r40BsBiOTALnzASvLb4qutGwPpL+jH2UKTCV5WJLXZFMzRnpZaRfeZGE8lMJ/i0+jv9H9G1FmVzE8UgB4rhw==", "dependencies": { "@aws-sdk/util-buffer-from": "3.295.0", "tslib": "^2.5.0" @@ -792,14 +836,16 @@ }, "core/create/node_modules/@aws-sdk/util-body-length-browser": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.295.0.tgz", + "integrity": "sha512-NbG4/RSHV1VueStPRclSo5zRjNUmcDlNAs29sniZF+YaN0+Ad7hEdu/YgJw39shBfUaurz2Wv0pufU3cxE5Tng==", "dependencies": { "tslib": "^2.5.0" } }, "core/create/node_modules/@aws-sdk/util-body-length-node": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.295.0.tgz", + "integrity": "sha512-dvGf8VBmrT66lM0n6P/h7wnlHS4Atafyivyl8f4TUCMvRdpqryvvrtnX6yYcq3T7VKQmas/2SOlgDvcrhGXaiw==", "dependencies": { "tslib": "^2.5.0" }, @@ -809,7 +855,8 @@ }, "core/create/node_modules/@aws-sdk/util-buffer-from": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.295.0.tgz", + "integrity": "sha512-5ezVEITQnrQKn+CU9qfZHgRp2nrrbX0Clmlm9aiNjAEQEPHY33tWl0t6n8h8yU+IpGiNRMWBVC4aSJaE5NA1mA==", "dependencies": { "@aws-sdk/is-array-buffer": "3.295.0", "tslib": "^2.5.0" @@ -820,7 +867,8 @@ }, "core/create/node_modules/@aws-sdk/util-config-provider": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.295.0.tgz", + "integrity": "sha512-/5Dl1aV2yI8YQjqwmg4RTnl/E9NmNsx7HIwBZt+dTcOrM0LMUwczQBFFcLyqCj/qv5y+VsvLoAAA/OiBT7hb3w==", "dependencies": { "tslib": "^2.5.0" }, @@ -830,7 +878,8 @@ }, "core/create/node_modules/@aws-sdk/util-defaults-mode-browser": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.296.0.tgz", + "integrity": "sha512-R+nzc0PuTMaOG3LV4FoS5W7oMAqqr8G1IyI+A4Q5iem6YDMF157qV5h6wpIt3A8n9YfjyssLsAT/WPfyv/M79w==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -843,7 +892,8 @@ }, "core/create/node_modules/@aws-sdk/util-defaults-mode-node": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.300.0.tgz", + "integrity": "sha512-a8tZsgkMBhnBlADyhDXMglFh6vkX6zXcJ4pnE9D3JrLDL0Fl50/Zk8FbePilEF2Dv7XRIOe4K70OZnNeeELJcg==", "dependencies": { "@aws-sdk/config-resolver": "3.300.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -858,7 +908,8 @@ }, "core/create/node_modules/@aws-sdk/util-endpoints": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.296.0.tgz", + "integrity": "sha512-YraGGLJepXM6HCTaqEGTFf8RFRBdJ0C6uG5k0kVhiXmYxBkeupn8J07CVp9jfWqcPYWElAnMGVEZKU1OjRo4HQ==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -869,7 +920,8 @@ }, "core/create/node_modules/@aws-sdk/util-hex-encoding": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.295.0.tgz", + "integrity": "sha512-XJcoVo41kHzhe28PBm/rqt5mdCp8R6abwiW9ug1dA6FOoPUO8kBUxDv6xaOmA2hfRvd2ocFfBXaUCBqUowkGcQ==", "dependencies": { "tslib": "^2.5.0" }, @@ -879,7 +931,8 @@ }, "core/create/node_modules/@aws-sdk/util-middleware": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.296.0.tgz", + "integrity": "sha512-MNWU+doVuX+mIehEManP6OP+f08T33qQpHoBqKIeKpn3TjZjMHG7ujACTkJiEOHUrnwTov7h0Sm+3OZwk3kh9w==", "dependencies": { "tslib": "^2.5.0" }, @@ -889,7 +942,8 @@ }, "core/create/node_modules/@aws-sdk/util-retry": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.296.0.tgz", + "integrity": "sha512-0mh7SqOMjuJ4vE423SzA/AfCLM68jykbfpEBkTmfqkpjkeQSW+UXHAUdXsMmfzIneiq7go5Z548F868C3cZnwQ==", "dependencies": { "@aws-sdk/service-error-classification": "3.296.0", "tslib": "^2.5.0" @@ -900,7 +954,8 @@ }, "core/create/node_modules/@aws-sdk/util-uri-escape": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.295.0.tgz", + "integrity": "sha512-1H5DcyIoXF8XcPBWf7wzHt0l+TW2EoR8Oq4gsVrPTQkHMTVclC2Yn8EF3gc4arwVBzwLulI9LMBE2L8fexGfTQ==", "dependencies": { "tslib": "^2.5.0" }, @@ -910,7 +965,8 @@ }, "core/create/node_modules/@aws-sdk/util-user-agent-browser": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.299.0.tgz", + "integrity": "sha512-TRPAemTDzqxCxbpVkXV+Sp9JbEo0JdT/W8qzP/uuOdglZlNXM+SadkOuNFmqr2KG83bJE6lvomGJcJb9vMN4XQ==", "dependencies": { "@aws-sdk/types": "3.296.0", "bowser": "^2.11.0", @@ -919,7 +975,8 @@ }, "core/create/node_modules/@aws-sdk/util-user-agent-node": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.300.0.tgz", + "integrity": "sha512-lBx4HxyTxxQiqGcmvOK4p09XC2YxmH6ANQXdXdiT28qM3OJjf5WLyl4FfdH7grDSryTFdF06FRFtJDFSuSWYrw==", "dependencies": { "@aws-sdk/node-config-provider": "3.300.0", "@aws-sdk/types": "3.296.0", @@ -939,7 +996,8 @@ }, "core/create/node_modules/@aws-sdk/util-utf8": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.295.0.tgz", + "integrity": "sha512-ITN8v3F63ZkA4sdmCtSbS/mhav4F0MEAiXDAUXtMJLNqVtaVcyQST4i9vNmPpIVthAPAtP0QjyF2tq/Di8bxtQ==", "dependencies": { "@aws-sdk/util-buffer-from": "3.295.0", "tslib": "^2.5.0" @@ -950,12 +1008,14 @@ }, "core/create/node_modules/@types/node": { "version": "12.20.55", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true }, "core/create/node_modules/code-suggester": { "version": "4.3.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/code-suggester/-/code-suggester-4.3.1.tgz", + "integrity": "sha512-QVW9uSIMl/KLF9yrjm2wm1h/o3j2WgGnQTH+o2+okVFlhopcJGW2Jv+CwvGGgfoSTxkcG3hocQee4ZZhdMhcew==", "dependencies": { "@octokit/rest": "^19.0.5", "@types/yargs": "^16.0.0", @@ -974,7 +1034,8 @@ }, "core/create/node_modules/fast-xml-parser": { "version": "4.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.1.2.tgz", + "integrity": "sha512-CDYeykkle1LiA/uqQyNwYpFbyF6Axec6YapmpUP+/RHWIoR1zKjocdvNaTsxCxZzQ6v9MLXaSYm9Qq0thv0DHg==", "dependencies": { "strnum": "^1.0.5" }, @@ -988,16 +1049,19 @@ }, "core/create/node_modules/parse-diff": { "version": "0.11.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.11.1.tgz", + "integrity": "sha512-Oq4j8LAOPOcssanQkIjxosjATBIEJhCxMCxPhMu+Ci4wdNmAEdx0O+a7gzbR2PyKXgKPvRLIN5g224+dJAsKHA==" }, "core/create/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "core/create/node_modules/type-fest": { "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=14.16" }, @@ -1007,21 +1071,24 @@ }, "core/create/node_modules/uuid": { "version": "8.3.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "bin": { "uuid": "dist/bin/uuid" } }, "core/create/node_modules/yaml": { "version": "2.2.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", + "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", "engines": { "node": ">= 14" } }, "core/create/node_modules/yargs": { "version": "16.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -1038,12 +1105,8 @@ "core/sandbox": { "version": "1.0.0", "license": "ISC", - "workspaces": [ - "packages/*" - ], "dependencies": { "@dotcom-tool-kit/base": "file:../../lib/base", - "@dotcom-tool-kit/monorepo": "file:../../plugins/monorepo", "@dotcom-tool-kit/node": "file:../../plugins/node", "@dotcom-tool-kit/package-json-hook": "file:../../plugins/package-json-hook", "dotcom-tool-kit": "file:../cli" @@ -1071,7 +1134,8 @@ }, "lib/base/node_modules/lru-cache": { "version": "6.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { "yallist": "^4.0.0" }, @@ -1081,7 +1145,8 @@ }, "lib/base/node_modules/semver": { "version": "7.6.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1094,7 +1159,8 @@ }, "lib/base/node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "lib/config": { "name": "@dotcom-tool-kit/config", @@ -1138,7 +1204,8 @@ }, "lib/doppler/node_modules/tslib": { "version": "2.6.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" }, "lib/error": { "name": "@dotcom-tool-kit/error", @@ -1154,7 +1221,8 @@ }, "lib/error/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "lib/logger": { "name": "@dotcom-tool-kit/logger", @@ -1180,7 +1248,8 @@ }, "lib/logger/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "lib/options": { "name": "@dotcom-tool-kit/options", @@ -1197,7 +1266,28 @@ }, "lib/options/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "lib/package-json-hook": { + "name": "@dotcom-tool-kit/package-json-hook", + "version": "4.2.0", + "extraneous": true, + "license": "ISC", + "dependencies": { + "@financial-times/package-json": "^3.0.0", + "lodash": "^4.17.21", + "tslib": "^2.3.1" + }, + "devDependencies": { + "@jest/globals": "^27.4.6", + "@types/lodash": "^4.14.185", + "winston": "^3.5.1" + }, + "engines": { + "node": "16.x || 18.x || 20.x", + "npm": "7.x || 8.x || 9.x || 10.x" + } }, "lib/plugin": { "name": "@dotcom-tool-kit/plugin", @@ -1232,7 +1322,37 @@ }, "lib/state/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "lib/types": { + "name": "@dotcom-tool-kit/types", + "version": "3.6.0", + "extraneous": true, + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/conflict": "^1.0.0", + "@dotcom-tool-kit/error": "^3.2.0", + "@dotcom-tool-kit/logger": "^3.4.0", + "@dotcom-tool-kit/validated": "^1.0.0", + "semver": "^7.3.7", + "tslib": "^2.3.1" + }, + "devDependencies": { + "@dotcom-tool-kit/schemas": "^1.0.0", + "@jest/globals": "^27.4.6", + "@types/prompts": "^2.0.14", + "@types/semver": "^7.3.9", + "winston": "^3.5.1", + "zod": "^3.22.4" + }, + "engines": { + "node": "16.x || 18.x || 20.x", + "npm": "7.x || 8.x || 9.x || 10.x" + }, + "peerDependencies": { + "zod": "^3.22.4" + } }, "lib/validated": { "name": "@dotcom-tool-kit/validated", @@ -1266,163 +1386,10 @@ "npm": "7.x || 8.x || 9.x || 10.x" } }, - "lib/vault/node_modules/@dotcom-reliability-kit/app-info": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/app-info/-/app-info-2.3.0.tgz", - "integrity": "sha512-LMyL1tmNOl5aRtBih4EewqXEUK8oOF7j4sa8WCnDUdVlJedUl09iZrBk5th20qvgk2DzO0b5XwKVPLsVWvutCg==", - "engines": { - "node": "16.x || 18.x || 20.x", - "npm": "7.x || 8.x || 9.x" - } - }, - "lib/vault/node_modules/@dotcom-reliability-kit/logger": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/logger/-/logger-2.4.2.tgz", - "integrity": "sha512-Gv5mist7h61Ostagp08KnyyCn25FgzSKRdpIPRTbd412pci8i3rHLwADHUROfDjvNX/bVRBd0sda9RCbkF6aIA==", - "dependencies": { - "@dotcom-reliability-kit/app-info": "^2.3.0", - "@dotcom-reliability-kit/serialize-error": "^2.2.1", - "lodash.clonedeep": "^4.5.0", - "pino": "^8.17.1" - }, - "engines": { - "node": "16.x || 18.x || 20.x", - "npm": "7.x || 8.x || 9.x" - }, - "peerDependencies": { - "pino-pretty": ">=7.0.0 <11.0.0" - } - }, - "lib/vault/node_modules/@dotcom-reliability-kit/serialize-error": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/serialize-error/-/serialize-error-2.2.1.tgz", - "integrity": "sha512-JP8skyGR3YcCo2tTZogYoLUPWrs5Se+d07MZfBeCXMb2+2BmM79/3V8B6HJ8jPFq6/f6nVVFbQ7VpgHnNk6T2Q==", - "engines": { - "node": "16.x || 18.x || 20.x", - "npm": "7.x || 8.x || 9.x" - } - }, - "lib/vault/node_modules/@financial-times/n-fetch": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@financial-times/n-fetch/-/n-fetch-1.0.1.tgz", - "integrity": "sha512-LG0F/8V3gQe1D2/0WuHNYFIB/D9w5RIgstZbcqqpF+jqODIWBN6LY2isJ6qs3R+he2ev0QacuS8EupvdEpYxag==", - "deprecated": "n-fetch is no longer supported. It will get security patches up until 2024-07-01", - "dependencies": { - "@dotcom-reliability-kit/logger": "^2.4.2", - "http-errors": "^2.0.0", - "node-fetch": "^2.7.0" - }, - "engines": { - "node": "16.x || 18.x", - "npm": "7.x || 8.x || 9.x" - } - }, - "lib/vault/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "lib/vault/node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "lib/vault/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "lib/vault/node_modules/pino": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.20.0.tgz", - "integrity": "sha512-uhIfMj5TVp+WynVASaVEJFTncTUe4dHBq6CWplu/vBgvGHhvBvQfxz+vcOrnnBQdORH3izaGEurLfNlq3YxdFQ==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.1.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^3.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.7.0", - "thread-stream": "^2.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "lib/vault/node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" - }, - "lib/vault/node_modules/sonic-boom": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", - "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "lib/vault/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "lib/vault/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, "lib/vault/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" - }, - "lib/vault/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "lib/vault/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "lib/wait-for-ok": { "name": "@dotcom-tool-kit/wait-for-ok", @@ -1444,12 +1411,14 @@ }, "lib/wait-for-ok/node_modules/@types/node": { "version": "12.20.55", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true }, "lib/wait-for-ok/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "node_modules/@actions/exec": { "version": "1.1.1", @@ -1475,7 +1444,8 @@ }, "node_modules/@apaleslimghost/boxen": { "version": "5.1.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@apaleslimghost/boxen/-/boxen-5.1.3.tgz", + "integrity": "sha512-UkSSOihJUY2VKdU0WE8NH6xgB/P1iMEODkaXlRqCh5WDZ/8weZq/eHblFJM+F9CCd+QMkIbp2TjCmJB1A9rTRg==", "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -1495,7 +1465,8 @@ }, "node_modules/@apaleslimghost/boxen/node_modules/camelcase": { "version": "6.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "engines": { "node": ">=10" }, @@ -1505,7 +1476,8 @@ }, "node_modules/@aws-crypto/crc32": { "version": "3.0.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", @@ -1514,7 +1486,8 @@ }, "node_modules/@aws-crypto/crc32c": { "version": "3.0.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", + "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", @@ -1523,14 +1496,16 @@ }, "node_modules/@aws-crypto/ie11-detection": { "version": "3.0.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", "dependencies": { "tslib": "^1.11.1" } }, "node_modules/@aws-crypto/sha1-browser": { "version": "3.0.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", + "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", "dependencies": { "@aws-crypto/ie11-detection": "^3.0.0", "@aws-crypto/supports-web-crypto": "^3.0.0", @@ -1543,7 +1518,8 @@ }, "node_modules/@aws-crypto/sha256-browser": { "version": "3.0.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", "dependencies": { "@aws-crypto/ie11-detection": "^3.0.0", "@aws-crypto/sha256-js": "^3.0.0", @@ -1557,7 +1533,8 @@ }, "node_modules/@aws-crypto/sha256-js": { "version": "3.0.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", @@ -1566,14 +1543,16 @@ }, "node_modules/@aws-crypto/supports-web-crypto": { "version": "3.0.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", "dependencies": { "tslib": "^1.11.1" } }, "node_modules/@aws-crypto/util": { "version": "3.0.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", "dependencies": { "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-utf8-browser": "^3.0.0", @@ -1582,7 +1561,8 @@ }, "node_modules/@aws-sdk/abort-controller": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.257.0.tgz", + "integrity": "sha512-ekWy391lOerS0ZECdhp/c+X7AToJIpfNrCPjuj3bKr+GMQYckGsYsdbm6AUD4sxBmfvuaQmVniSXWovaxwcFcQ==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -1593,18 +1573,21 @@ }, "node_modules/@aws-sdk/abort-controller/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/chunked-blob-reader": { "version": "3.188.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/chunked-blob-reader/-/chunked-blob-reader-3.188.0.tgz", + "integrity": "sha512-zkPRFZZPL3eH+kH86LDYYXImiClA1/sW60zYOjse9Pgka+eDJlvBN6hcYxwDEKjcwATYiSRR1aVQHcfCinlGXg==", "dependencies": { "tslib": "^2.3.1" } }, "node_modules/@aws-sdk/chunked-blob-reader-native": { "version": "3.208.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/chunked-blob-reader-native/-/chunked-blob-reader-native-3.208.0.tgz", + "integrity": "sha512-JeOZ95PW+fJ6bbuqPySYqLqHk1n4+4ueEEraJsiUrPBV0S1ZtyvOGHcnGztKUjr2PYNaiexmpWuvUve9K12HRA==", "dependencies": { "@aws-sdk/util-base64": "3.208.0", "tslib": "^2.3.1" @@ -1612,15 +1595,18 @@ }, "node_modules/@aws-sdk/chunked-blob-reader-native/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/chunked-blob-reader/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/client-iam": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.301.0.tgz", + "integrity": "sha512-CO8c3x7Q+BJpjZxTt8sPH2VK+8IZRn6ecc7E35GUd0gk8nUcz6Onu/h28Sn6kHkLZBQmLw3ngifkaIzDydmEew==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -1666,7 +1652,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/abort-controller": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.296.0.tgz", + "integrity": "sha512-gNUFBlBw6+sEMfDjPVa83iscpQwXBS4uoiZXnfeQ6s6tnaxqQpJDrBBmNvYqDEXNdaAJX4FhayEwkSvtir/f3A==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -1677,7 +1664,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/client-sso": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.301.0.tgz", + "integrity": "sha512-nABoNn0O79PL72jg2oy9gR/MLmM4opZ6nQefXvXUb6RzlITZCCZ6uKkGcH2LMxOcRu6qQlY+uauX+9p0GJexlg==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -1718,7 +1706,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/client-sso-oidc": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.301.0.tgz", + "integrity": "sha512-bCBA70/7gkrk1s1iGWt3st4p9yNIkQ3e+KV8Kx3uzRvjD0f7KltGqSNA28453tsa7ko+H/V4c7fzrJnWaQomCg==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -1759,7 +1748,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/client-sts": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.301.0.tgz", + "integrity": "sha512-OS8wE21Lxd8aT8PMj/dusCUZKXmXaxnSI4RIO3M8w/ZPRMKkBHtzB+JXbzUcpGGxvt9mse8l6w9iLIE6XuHmig==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -1804,7 +1794,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/config-resolver": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.300.0.tgz", + "integrity": "sha512-u3YS+XWjoHmH9wh07Lv+HueYZek/wTO8tlGvVzrlACpaS1JrALuCw8UsJUHNDack63xh9v4oMf+7c0kjuqbmtA==", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-config-provider": "3.295.0", @@ -1817,7 +1808,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-env": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.296.0.tgz", + "integrity": "sha512-eDWSU3p04gytkkVXnYn05YzrP5SEaj/DQiafd4y+iBl8IFfF3zM6982rs6qFhvpwrHeSbLqHNfKR1HDWVwfG5g==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -1829,7 +1821,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-imds": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.300.0.tgz", + "integrity": "sha512-l7ZFGlr4TjhS0FIt3XwuAJYNAbQ4eDsovMMUVYLDPti1NxlbQDH85xAyaDWF9dU1Gulrpfzz9Ei7q4GYFFPHnQ==", "dependencies": { "@aws-sdk/node-config-provider": "3.300.0", "@aws-sdk/property-provider": "3.296.0", @@ -1843,7 +1836,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-ini": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.301.0.tgz", + "integrity": "sha512-tAsNH6vQZ7U459FzjStIXoi3HZAsl6y8CMf6364dyisZ0xiCiVHLxziTmSxntcR0560NFFSOY1WS5MrbIIneGQ==", "dependencies": { "@aws-sdk/credential-provider-env": "3.296.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -1861,7 +1855,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-node": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.301.0.tgz", + "integrity": "sha512-WNz7+HoGEkAHaOL1d4D2c/LxYS3zBdqzLs7uYgekoqTSMQhTaIMyJIJgChcklAmV/yM1+2c3lS1NEtCCz3/Vxw==", "dependencies": { "@aws-sdk/credential-provider-env": "3.296.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -1880,7 +1875,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-process": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.300.0.tgz", + "integrity": "sha512-HGBLXupPU2XTvHmlcbSgH/zLyhQ1joLIBAvKvyxyjQTIeFSDOufDqRBY4CzNzPv0yJlvSi3gAfL36CR9dh2R4w==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/shared-ini-file-loader": "3.300.0", @@ -1893,7 +1889,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-sso": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.301.0.tgz", + "integrity": "sha512-5mGoBX5WmZRuL3RIWgdhMbnKYHSmM54qEFjbtRiFXZQ1QSItom1ICBCyIEoNMZQ20+iRxyTgf/fGCJrXhDlIqQ==", "dependencies": { "@aws-sdk/client-sso": "3.301.0", "@aws-sdk/property-provider": "3.296.0", @@ -1908,7 +1905,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/credential-provider-web-identity": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.296.0.tgz", + "integrity": "sha512-Rl6Ohoekxe+pccA55XXQDW5wApbg3rGWr6FkmPRcg7Ld6Vfe+HL8OtfsFf83/0eoFerevbif+00BdknXWT05LA==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -1920,7 +1918,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/fetch-http-handler": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.296.0.tgz", + "integrity": "sha512-wHuKQ+PGKQkYGVuIGscbcbbASl8yIVOSC+QTrZQ4PNsMDvQd9ey2npsmxZk1Z2ULaxY+qYtZCmByyGc8k51TtQ==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/querystring-builder": "3.296.0", @@ -1931,7 +1930,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/hash-node": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.296.0.tgz", + "integrity": "sha512-01Sgxm0NE3rtEznLY8vx1bfNsIeM5Sk5SjY9RXqnvCf9EyaKH9x5FMS/DX/SgDdIYi3aXbTwiwScNVCNBzOIQA==", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-buffer-from": "3.295.0", @@ -1944,7 +1944,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/invalid-dependency": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.296.0.tgz", + "integrity": "sha512-dmy4fUds0woHGjxwziaSYCLtb/SOfoEeQjW0GFvHj+YGFyY5hJzna4C759Tt8X5obh1evUXlQcH+FL7TS+7tRQ==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -1952,7 +1953,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/is-array-buffer": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.295.0.tgz", + "integrity": "sha512-SCIt10cr5dud7hvwveU4wkLjvkGssJ3GrcbHCds2NwI+JHmpcaaNYLAqi305JAuT29T36U5ssTFDSmrrEOcfag==", "dependencies": { "tslib": "^2.5.0" }, @@ -1962,7 +1964,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-content-length": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.296.0.tgz", + "integrity": "sha512-e7lJm3kkC2pWZdIw23gpMUk1GrpRTBRqhdFfVwyduXw6Wo4nBYv8Z5MOYy3/SlpjE1BDCaPBoZ3O19cO3arHxg==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -1974,7 +1977,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-endpoint": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.299.0.tgz", + "integrity": "sha512-37BGxHem6yKjSC6zG2xPjvjE7APIDIvwkxL+/K1Jz9+T6AZITcs7tx5y6mIfvaHsdPuCKjrl7Wzg/9jgUKuLkw==", "dependencies": { "@aws-sdk/middleware-serde": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -1988,7 +1992,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-host-header": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.296.0.tgz", + "integrity": "sha512-V47dFtfkX5lXWv9GDp71gZVCRws4fEdQ9QF9BQ/2UMSNrYjQLg6mFe7NibH+IJoNOid2FIwWIl94Eos636VGYQ==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2000,7 +2005,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-logger": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.296.0.tgz", + "integrity": "sha512-LzfEEFyBR9LXdWwLdtBrmi1vLdzgdJNntEgzqktVF8LwaCyY+9xIE6TGu/2V+9fJHAwECxjOC1eQbNQdAZ0Tmw==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2011,7 +2017,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-recursion-detection": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.296.0.tgz", + "integrity": "sha512-UG7TLDPz9ImQG0uVklHTxE9Us7rTImwN+6el6qZCpoTBuGeXgOkfb0/p8izJyFgY/hMUR4cZqs7IdCDUkxQF3w==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2023,7 +2030,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-retry": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.300.0.tgz", + "integrity": "sha512-c3tj0Uc64mqnsosAjRBQbit0EUOd0OKrqC5eDB3YCJyLWQSlYRBk4ZBBbN2qTfo3ZCDP+tHgWxRduQlV6Knezg==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/service-error-classification": "3.296.0", @@ -2039,7 +2047,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-sdk-sts": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.299.0.tgz", + "integrity": "sha512-yE7IiMQpF1FYqLSYOei4AYM9z62ayFfMMyhKE9IFs+TVaag97uz8NaRlr88HDTcBCZ0CMl6UwNJlZytPD4NjCw==", "dependencies": { "@aws-sdk/middleware-signing": "3.299.0", "@aws-sdk/types": "3.296.0", @@ -2051,7 +2060,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-serde": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.296.0.tgz", + "integrity": "sha512-xk2PpWAAX758oUTGkGBAncpOr7ddIXisjD2Y2r9DDXuE4JMho2x6zcrVSiYsGIQ6MHZ9XNJKBVDiK9PA4iQWGQ==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2062,7 +2072,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-signing": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.299.0.tgz", + "integrity": "sha512-anhrjeNuo0470QodEmzteFMnqABNebL900yhfODySXCMiaoeTBpo8Qd8t4q4O8PizA7FeLYA3l/5tb/udp7qew==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/protocol-http": "3.296.0", @@ -2077,7 +2088,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-stack": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.296.0.tgz", + "integrity": "sha512-Rgo7/mdk9tt4qa9+pzG3AoGNhuj7NmnF5H+3DoPm75h58BYP8hKbKobdPGgI2rZLPtO3PGgmyw/4K4tQJPIZ8g==", "dependencies": { "tslib": "^2.5.0" }, @@ -2087,7 +2099,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/middleware-user-agent": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.299.0.tgz", + "integrity": "sha512-Brm5UcbRhuVVmmbpDN8/WSJPCHogV64jGXL5upfL+iJ0c5eZ57LXOZ8kz++t3BU1rEkSIXHJanneEmn7Wbd5sA==", "dependencies": { "@aws-sdk/protocol-http": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2100,7 +2113,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/node-config-provider": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.300.0.tgz", + "integrity": "sha512-60XJV+eW1FyyRNT75kAGdqDHLpWWqnZeCrEyufqQ3BXhhbD1l6oHy5W573DccEO84/0gQYlNbKL8hd8+iB59vA==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/shared-ini-file-loader": "3.300.0", @@ -2113,7 +2127,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/node-http-handler": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.296.0.tgz", + "integrity": "sha512-D15jjPqYSNhEq58BwkmIpD3VwqG4bL5acAaNu5wWAI4S4236JlG+nmpi3gEeE25z1KCwtBl7G30fVRgXYJ2CWA==", "dependencies": { "@aws-sdk/abort-controller": "3.296.0", "@aws-sdk/protocol-http": "3.296.0", @@ -2127,7 +2142,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/property-provider": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.296.0.tgz", + "integrity": "sha512-kjczxE9Od5LoAKQOmxVWISJ9oPG3aCsB+2+NdI+k9EJFDXUUdMcVV3Skei5uHGgKLMsI6CZy8ezZx6YxOSLSew==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2138,7 +2154,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/protocol-http": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.296.0.tgz", + "integrity": "sha512-0U1Z/+tpwdRiSToWo1bpdkbTzjbLugTnd02ATjvK4B7zi363SUGlKfoWgV+v7FU/22CIUI1ZIe7XzXvq5rJfjA==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2149,7 +2166,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/querystring-builder": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.296.0.tgz", + "integrity": "sha512-+ZrZdTRaVI1R1xKQNrTwuiRoPateUaJ/DNw/myJpTPt+ZRg0H7LKBGaJYwL4pl5l/z1UM/E1fOttSfSW7GHxfw==", "dependencies": { "@aws-sdk/types": "3.296.0", "@aws-sdk/util-uri-escape": "3.295.0", @@ -2161,7 +2179,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/querystring-parser": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.296.0.tgz", + "integrity": "sha512-nLNZKVQfK42euv7101cE5qfg17YCtGcfccx3B5XSAzvyTROR46kwYqbEvYSsWisbZoRhbQc905gB/5E0U5HDIw==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2172,14 +2191,16 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/service-error-classification": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.296.0.tgz", + "integrity": "sha512-YIsWSQ38e1+FqXz3CMrkKS0JD8OLlHf6I72PJhbfegePpQQFqi9R8OREjP5V7UR9Z972yruv4i96ROH6SCtmoA==", "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/shared-ini-file-loader": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.300.0.tgz", + "integrity": "sha512-xA+V08AMsb1EcNJ2UF896T4I3f6Q/H56Z3gTwcXyFXsCY3lYkEB2MEdST+x4+20emELkYjtu5SNsGgUCBehR7g==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2190,7 +2211,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/signature-v4": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.299.0.tgz", + "integrity": "sha512-3TtP+S3Tu0Q2/EwJLnN+IEok9nRyez79f6vprqXbC9Lex623cqh/OOYSy2oUjFlIgsIOLPum87/1bfcznYW+yQ==", "dependencies": { "@aws-sdk/is-array-buffer": "3.295.0", "@aws-sdk/types": "3.296.0", @@ -2206,7 +2228,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/smithy-client": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.296.0.tgz", + "integrity": "sha512-HEpsLNozGe9XOWouq5A1TFw5KhFodi8tZqYVNEbSpLoRR+EQKf6OCRvKIRkOn7FnnaOasOR1n7S0D51UG6/irw==", "dependencies": { "@aws-sdk/middleware-stack": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2218,7 +2241,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/token-providers": { "version": "3.301.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.301.0.tgz", + "integrity": "sha512-TgchzkIOLGMhL3dFKGHyztZ4/HOM/WvJC0bRxvrWTs+iDHRaaKNpzW1RzCVCtbH8F/B9h5qPdRFJ6jTHtCKf4A==", "dependencies": { "@aws-sdk/client-sso-oidc": "3.301.0", "@aws-sdk/property-provider": "3.296.0", @@ -2232,7 +2256,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/types": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.296.0.tgz", + "integrity": "sha512-s0wIac64rrMEo2ioUxP9IarGiiCGmelCspNcoNTPSjGl25QqjhyfQqTeGgS58qJ4fHoQb07qra39930xp1IzJg==", "dependencies": { "tslib": "^2.5.0" }, @@ -2242,7 +2267,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/url-parser": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.296.0.tgz", + "integrity": "sha512-nBgeGF+ziuDSLz+y8UAl6zL2tXxDwh3wqeXFe9ZcR4YW71BWuh+vEqEsaEMutOrfnJacCrYKTs9TkIOW41cEGg==", "dependencies": { "@aws-sdk/querystring-parser": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2251,7 +2277,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-base64": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.295.0.tgz", + "integrity": "sha512-z1r40BsBiOTALnzASvLb4qutGwPpL+jH2UKTCV5WJLXZFMzRnpZaRfeZGE8lMJ/i0+jv9H9G1FmVzE8UgB4rhw==", "dependencies": { "@aws-sdk/util-buffer-from": "3.295.0", "tslib": "^2.5.0" @@ -2262,14 +2289,16 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-body-length-browser": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.295.0.tgz", + "integrity": "sha512-NbG4/RSHV1VueStPRclSo5zRjNUmcDlNAs29sniZF+YaN0+Ad7hEdu/YgJw39shBfUaurz2Wv0pufU3cxE5Tng==", "dependencies": { "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-body-length-node": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.295.0.tgz", + "integrity": "sha512-dvGf8VBmrT66lM0n6P/h7wnlHS4Atafyivyl8f4TUCMvRdpqryvvrtnX6yYcq3T7VKQmas/2SOlgDvcrhGXaiw==", "dependencies": { "tslib": "^2.5.0" }, @@ -2279,7 +2308,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-buffer-from": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.295.0.tgz", + "integrity": "sha512-5ezVEITQnrQKn+CU9qfZHgRp2nrrbX0Clmlm9aiNjAEQEPHY33tWl0t6n8h8yU+IpGiNRMWBVC4aSJaE5NA1mA==", "dependencies": { "@aws-sdk/is-array-buffer": "3.295.0", "tslib": "^2.5.0" @@ -2290,7 +2320,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-config-provider": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.295.0.tgz", + "integrity": "sha512-/5Dl1aV2yI8YQjqwmg4RTnl/E9NmNsx7HIwBZt+dTcOrM0LMUwczQBFFcLyqCj/qv5y+VsvLoAAA/OiBT7hb3w==", "dependencies": { "tslib": "^2.5.0" }, @@ -2300,7 +2331,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-defaults-mode-browser": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.296.0.tgz", + "integrity": "sha512-R+nzc0PuTMaOG3LV4FoS5W7oMAqqr8G1IyI+A4Q5iem6YDMF157qV5h6wpIt3A8n9YfjyssLsAT/WPfyv/M79w==", "dependencies": { "@aws-sdk/property-provider": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2313,7 +2345,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-defaults-mode-node": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.300.0.tgz", + "integrity": "sha512-a8tZsgkMBhnBlADyhDXMglFh6vkX6zXcJ4pnE9D3JrLDL0Fl50/Zk8FbePilEF2Dv7XRIOe4K70OZnNeeELJcg==", "dependencies": { "@aws-sdk/config-resolver": "3.300.0", "@aws-sdk/credential-provider-imds": "3.300.0", @@ -2328,7 +2361,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-endpoints": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.296.0.tgz", + "integrity": "sha512-YraGGLJepXM6HCTaqEGTFf8RFRBdJ0C6uG5k0kVhiXmYxBkeupn8J07CVp9jfWqcPYWElAnMGVEZKU1OjRo4HQ==", "dependencies": { "@aws-sdk/types": "3.296.0", "tslib": "^2.5.0" @@ -2339,7 +2373,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-hex-encoding": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.295.0.tgz", + "integrity": "sha512-XJcoVo41kHzhe28PBm/rqt5mdCp8R6abwiW9ug1dA6FOoPUO8kBUxDv6xaOmA2hfRvd2ocFfBXaUCBqUowkGcQ==", "dependencies": { "tslib": "^2.5.0" }, @@ -2349,7 +2384,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-middleware": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.296.0.tgz", + "integrity": "sha512-MNWU+doVuX+mIehEManP6OP+f08T33qQpHoBqKIeKpn3TjZjMHG7ujACTkJiEOHUrnwTov7h0Sm+3OZwk3kh9w==", "dependencies": { "tslib": "^2.5.0" }, @@ -2359,7 +2395,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-retry": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.296.0.tgz", + "integrity": "sha512-0mh7SqOMjuJ4vE423SzA/AfCLM68jykbfpEBkTmfqkpjkeQSW+UXHAUdXsMmfzIneiq7go5Z548F868C3cZnwQ==", "dependencies": { "@aws-sdk/service-error-classification": "3.296.0", "tslib": "^2.5.0" @@ -2370,7 +2407,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-uri-escape": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.295.0.tgz", + "integrity": "sha512-1H5DcyIoXF8XcPBWf7wzHt0l+TW2EoR8Oq4gsVrPTQkHMTVclC2Yn8EF3gc4arwVBzwLulI9LMBE2L8fexGfTQ==", "dependencies": { "tslib": "^2.5.0" }, @@ -2380,7 +2418,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-user-agent-browser": { "version": "3.299.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.299.0.tgz", + "integrity": "sha512-TRPAemTDzqxCxbpVkXV+Sp9JbEo0JdT/W8qzP/uuOdglZlNXM+SadkOuNFmqr2KG83bJE6lvomGJcJb9vMN4XQ==", "dependencies": { "@aws-sdk/types": "3.296.0", "bowser": "^2.11.0", @@ -2389,7 +2428,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-user-agent-node": { "version": "3.300.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.300.0.tgz", + "integrity": "sha512-lBx4HxyTxxQiqGcmvOK4p09XC2YxmH6ANQXdXdiT28qM3OJjf5WLyl4FfdH7grDSryTFdF06FRFtJDFSuSWYrw==", "dependencies": { "@aws-sdk/node-config-provider": "3.300.0", "@aws-sdk/types": "3.296.0", @@ -2409,7 +2449,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-utf8": { "version": "3.295.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.295.0.tgz", + "integrity": "sha512-ITN8v3F63ZkA4sdmCtSbS/mhav4F0MEAiXDAUXtMJLNqVtaVcyQST4i9vNmPpIVthAPAtP0QjyF2tq/Di8bxtQ==", "dependencies": { "@aws-sdk/util-buffer-from": "3.295.0", "tslib": "^2.5.0" @@ -2420,7 +2461,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/@aws-sdk/util-waiter": { "version": "3.296.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.296.0.tgz", + "integrity": "sha512-L57uIC74VyTjAdCH0wQqtvJtwK4+gIT/51K/BJHEqVg6C1pOwgrdT6dHC3q8b+gdOrZ6Ff/vTEfh7FZmVcPPjg==", "dependencies": { "@aws-sdk/abort-controller": "3.296.0", "@aws-sdk/types": "3.296.0", @@ -2432,7 +2474,8 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/fast-xml-parser": { "version": "4.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.1.2.tgz", + "integrity": "sha512-CDYeykkle1LiA/uqQyNwYpFbyF6Axec6YapmpUP+/RHWIoR1zKjocdvNaTsxCxZzQ6v9MLXaSYm9Qq0thv0DHg==", "dependencies": { "strnum": "^1.0.5" }, @@ -2446,18 +2489,21 @@ }, "node_modules/@aws-sdk/client-iam/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/client-iam/node_modules/uuid": { "version": "8.3.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/@aws-sdk/client-lambda": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.264.0.tgz", + "integrity": "sha512-Z7EnWd1PveFdcSAkqpbMQO/iOBETKAs6/RV5ZfDtNmtzku2FGk02Xm76eQnkJrUNTWesEWw/am03cK2d7brBGw==", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", @@ -2503,7 +2549,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sso": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.264.0.tgz", + "integrity": "sha512-p+7sYpRcdv9omnnsPhD/vOFuZ1SpfV62ZgistBK/RDsQg2W9SIWQRW1KPt7gOCQ0nwp4efntw4Sle0LjS7ykxg==", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", @@ -2545,7 +2592,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sso-oidc": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.264.0.tgz", + "integrity": "sha512-82hGEbfsD4lBGIF1q8o82jTNSgBCcBpfFsvA+ltZf0bh4ChIWOi4vVvg8G+zVQN1mm/Rj8vWYO/D0tNF8OSyWw==", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", @@ -2587,7 +2635,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sts": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.264.0.tgz", + "integrity": "sha512-sco1jREkDdds4Z3V19Vlu/YpBHSzeEt1KFqOPnbjFw7pSakRNzpyWmLLxOwWjwgGKt6pSF3Aw0ZOMYsAUDc5qQ==", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", @@ -2633,7 +2682,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-ini": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.264.0.tgz", + "integrity": "sha512-UU5NNlfn+Go+5PLBzyTH1YE3r/pgykpE4QYFon87sCnEQnQH9xmlRTW1f1cBSQ9kivbFZd2/C2X3qhB3fe2JfA==", "peer": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.257.0", @@ -2652,7 +2702,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-node": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.264.0.tgz", + "integrity": "sha512-DPzL7oawcILs5Mduim9Z8SVeJaUpaDRVbUIrBHsMBu+N7Zuqtzr+0ckHc1bEi3iYq2QUCk5pH5vpQaZYkMlbtw==", "peer": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.257.0", @@ -2672,7 +2723,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-sso": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.264.0.tgz", + "integrity": "sha512-CJuAlqIIJap6LXoqimvEAnYZ7Kb5pTbiS3e+aY+fajO3OPujmQpHuiY8kOmscjwZ4ErJdEskivcTGwXph0dPZQ==", "peer": true, "dependencies": { "@aws-sdk/client-sso": "3.264.0", @@ -2688,7 +2740,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-endpoint": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.264.0.tgz", + "integrity": "sha512-H9JEAug3Oo3IA2wZIplVVF6NtauCIjICXWgbNbA8Im+I2KPe0jWtOdtQv4U+tqHe9T4zIixaCM3gjUBld+FoOA==", "peer": true, "dependencies": { "@aws-sdk/middleware-serde": "3.257.0", @@ -2706,7 +2759,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/smithy-client": { "version": "3.261.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.261.0.tgz", + "integrity": "sha512-j8XQEa3caZUVFVZfhJjaskw80O/tB+IXu84HMN44N7UkXaCFHirUsNjTDztJhnVXf/gKXzIqUqprfRnOvwLtIg==", "peer": true, "dependencies": { "@aws-sdk/middleware-stack": "3.257.0", @@ -2719,7 +2773,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/token-providers": { "version": "3.264.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.264.0.tgz", + "integrity": "sha512-1N54FCdBJRqrwFWHUoDpGI0rKhI29Or9ZwGjjcBzKzLhz5sEF/DEhuID7h1/KKEkXdQ0+lmXOFGMMrahrMpOow==", "peer": true, "dependencies": { "@aws-sdk/client-sso-oidc": "3.264.0", @@ -2734,7 +2789,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-defaults-mode-browser": { "version": "3.261.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.261.0.tgz", + "integrity": "sha512-lX3X1NfzQVV6cakepGV24uRcqevlDnQ8VgaCV8dhnw1FVThueFigyoFaUA02+uRXbV9KIbNWkEvweNtm2wvyDw==", "peer": true, "dependencies": { "@aws-sdk/property-provider": "3.257.0", @@ -2748,7 +2804,8 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-defaults-mode-node": { "version": "3.261.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.261.0.tgz", + "integrity": "sha512-4AK6yu4bOmHSocUdbGoEHbNXB09UA58ON2HBHY4NxMBuFBAd9XB2tYiyhce+Cm+o+lHbS8oQnw0VZw16WMzzew==", "peer": true, "dependencies": { "@aws-sdk/config-resolver": "3.259.0", @@ -2764,12 +2821,14 @@ }, "node_modules/@aws-sdk/client-lambda/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "peer": true }, "node_modules/@aws-sdk/client-s3": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.259.0.tgz", + "integrity": "sha512-yZy7oTTqPAn5H1SxbsynzVRr6kSf5hJQYl00P1dpzsAjTJmRzV4CdHwUxsBkyfUeC6u324iJi9zir1v8HHgUJw==", "dependencies": { "@aws-crypto/sha1-browser": "3.0.0", "@aws-crypto/sha256-browser": "3.0.0", @@ -2832,11 +2891,13 @@ }, "node_modules/@aws-sdk/client-s3/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/client-sso": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.259.0.tgz", + "integrity": "sha512-TKi9Lj0zqxsrQWOZ+e4WchNDtLDz6B+ahMzYDIOFlglDPPEzbZE//PBMZCba/AAIe6U3xaUQSnni+4mNbRLg7Q==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -2877,7 +2938,8 @@ }, "node_modules/@aws-sdk/client-sso-oidc": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.259.0.tgz", + "integrity": "sha512-TKpUX55qLM35sQXx96VnB/ZcQCcBxVU/0j0wqL8Hij+blD7fy6KrGGJPORzRphmFg8Ehf1IoCivFxrQwLrjZ6A==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -2918,15 +2980,18 @@ }, "node_modules/@aws-sdk/client-sso-oidc/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/client-sso/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/client-sts": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.259.0.tgz", + "integrity": "sha512-LXqua4FoXxR30sM4BSwmPI6x0YmDTw6yQhxQQXA5hrx+YwUf8CSpa0K6Xwfv8M5+zP0uHfY1iVxx/rnT8FOEmA==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -2971,11 +3036,13 @@ }, "node_modules/@aws-sdk/client-sts/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/config-resolver": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.259.0.tgz", + "integrity": "sha512-gViMRsc4Ye6+nzJ0OYTZIT8m4glIAdtugN2Sr/t6P2iJW5X0bSL/EcbcHBgsve1lHjeGPeyzVkT7UnyGOZ5Z/A==", "dependencies": { "@aws-sdk/signature-v4": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -2989,11 +3056,13 @@ }, "node_modules/@aws-sdk/config-resolver/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/credential-provider-env": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.257.0.tgz", + "integrity": "sha512-GsmBi5Di6hk1JAi1iB6/LCY8o+GmlCvJoB7wuoVmXI3VxRVwptUVjuj8EtJbIrVGrF9dSuIRPCzUoSuzEzYGlg==", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3005,11 +3074,13 @@ }, "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/credential-provider-imds": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.259.0.tgz", + "integrity": "sha512-yCxoYWZAaDrCUEWxRfrpB0Mp1cFgJEMYW8T6GIb/+DQ5QLpZmorgaVD/j90QXupqFrR5tlxwuskBIkdD2E9YNg==", "dependencies": { "@aws-sdk/node-config-provider": "3.259.0", "@aws-sdk/property-provider": "3.257.0", @@ -3023,11 +3094,13 @@ }, "node_modules/@aws-sdk/credential-provider-imds/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/credential-provider-ini": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.259.0.tgz", + "integrity": "sha512-/sjZv+XvcSMnvDTsau0cHxMFcbz4f4ksvgu10JQ1PpcH5CPQJviDJjZRzzijcOuMZ3SOO0skyuYU6tjY18cgIg==", "dependencies": { "@aws-sdk/credential-provider-env": "3.257.0", "@aws-sdk/credential-provider-imds": "3.259.0", @@ -3045,11 +3118,13 @@ }, "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/credential-provider-node": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.259.0.tgz", + "integrity": "sha512-7doM6hCPTZD0H+A7VtElLY4Ztuhg3MbjoHs00TyPZNCym7f/AKmKi9Exiw1tGgxTJkfn/SzcAWz+TyqMP078ow==", "dependencies": { "@aws-sdk/credential-provider-env": "3.257.0", "@aws-sdk/credential-provider-imds": "3.259.0", @@ -3068,11 +3143,13 @@ }, "node_modules/@aws-sdk/credential-provider-node/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/credential-provider-process": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.257.0.tgz", + "integrity": "sha512-xK8uYeNXaclaBCGrLi4z2pxPRngqLf5BM5jg2fn57zqvlL9V5gJF972FehrVBL0bfp1/laG0ZJtD2K2sapyWAw==", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/shared-ini-file-loader": "3.257.0", @@ -3085,11 +3162,13 @@ }, "node_modules/@aws-sdk/credential-provider-process/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/credential-provider-sso": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.259.0.tgz", + "integrity": "sha512-cz+8aNKxvZ8ikd0JDcB9MZredOJNRZkbco8QAM0gXfy6ziyX+23oU8+aekZljDzQR5QNRouvMz1KKmBxZLpNyg==", "dependencies": { "@aws-sdk/client-sso": "3.259.0", "@aws-sdk/property-provider": "3.257.0", @@ -3104,11 +3183,13 @@ }, "node_modules/@aws-sdk/credential-provider-sso/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/credential-provider-web-identity": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.257.0.tgz", + "integrity": "sha512-Cm0uvRv4JuIbD0Kp3W0J/vwjADIyCx8HoZi5yg+QIi5nilocuTQ3ajvLeuPVSvFvdy+yaxSc5FxNXquWt7Mngw==", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3120,11 +3201,13 @@ }, "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/eventstream-codec": { "version": "3.258.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-codec/-/eventstream-codec-3.258.0.tgz", + "integrity": "sha512-DTd6aggICXOH74tBQEliwLbeoXRbQ3uROBWYl7DdrbAemzHACDFzPCXXa9MTJMZcq3Tva8/E/3bv1fXuU/xkAA==", "dependencies": { "@aws-crypto/crc32": "3.0.0", "@aws-sdk/types": "3.257.0", @@ -3134,11 +3217,13 @@ }, "node_modules/@aws-sdk/eventstream-codec/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/eventstream-serde-browser": { "version": "3.258.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-serde-browser/-/eventstream-serde-browser-3.258.0.tgz", + "integrity": "sha512-bRcNxDrBFd0UsrLh88kwpvGDHjVupZP3gPJ5b7wseCuuWJzp56/7hNI97IywgARta91rcaf4K147VxFkSNaVlw==", "dependencies": { "@aws-sdk/eventstream-serde-universal": "3.258.0", "@aws-sdk/types": "3.257.0", @@ -3150,11 +3235,13 @@ }, "node_modules/@aws-sdk/eventstream-serde-browser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/eventstream-serde-config-resolver": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.257.0.tgz", + "integrity": "sha512-YbUETgkcFqPJmwcBozHbx3Xloh7mPk9SunNB+Ndy8egwV3L/jNZnEzZnPOtWbD10AXSuJvSbGQ8+l4FblRqZqw==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3165,11 +3252,13 @@ }, "node_modules/@aws-sdk/eventstream-serde-config-resolver/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/eventstream-serde-node": { "version": "3.258.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-serde-node/-/eventstream-serde-node-3.258.0.tgz", + "integrity": "sha512-KvuitKB3fK1ZjWcB+U6d8JNv0WJtE1zvW5DXI/OabzaIR4i/LNis7469EwTsEkTqG3mV3wUa6cBA6kBSJWTVeA==", "dependencies": { "@aws-sdk/eventstream-serde-universal": "3.258.0", "@aws-sdk/types": "3.257.0", @@ -3181,11 +3270,13 @@ }, "node_modules/@aws-sdk/eventstream-serde-node/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/eventstream-serde-universal": { "version": "3.258.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-serde-universal/-/eventstream-serde-universal-3.258.0.tgz", + "integrity": "sha512-woHNrBp8YSIaf3mcRJA0SyKFnjeLX2fRudLZq9wd555Zz/U7f45AuZOpXlU66tIZiYJI1xm32VRSIYfpIwXI+A==", "dependencies": { "@aws-sdk/eventstream-codec": "3.258.0", "@aws-sdk/types": "3.257.0", @@ -3197,11 +3288,13 @@ }, "node_modules/@aws-sdk/eventstream-serde-universal/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/fetch-http-handler": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.257.0.tgz", + "integrity": "sha512-zOF+RzQ+wfF7tq7tGUdPcqUTh3+k2f8KCVJE07A8kCopVq4nBu4NH6Eq29Tjpwdya3YlKvE+kFssuQRRRRex+Q==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/querystring-builder": "3.257.0", @@ -3212,11 +3305,13 @@ }, "node_modules/@aws-sdk/fetch-http-handler/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/hash-blob-browser": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.257.0.tgz", + "integrity": "sha512-3Nrcci3pCCc0ZILMGa/oUMq9le6nhvgCoVxFy5skYs/mQu4QnA8HcK0u4bTueW41rBj0ZW6BHLk/2SmigIkjCQ==", "dependencies": { "@aws-sdk/chunked-blob-reader": "3.188.0", "@aws-sdk/chunked-blob-reader-native": "3.208.0", @@ -3226,11 +3321,13 @@ }, "node_modules/@aws-sdk/hash-blob-browser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/hash-node": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.257.0.tgz", + "integrity": "sha512-W/USUuea5Ep3OJ2U7Ve8/5KN1YsDun2WzOFUxc1PyxXP5pW6OgC15/op0e+bmWPG851clvp5S8ZuroUr3aKi3Q==", "dependencies": { "@aws-sdk/types": "3.257.0", "@aws-sdk/util-buffer-from": "3.208.0", @@ -3243,11 +3340,13 @@ }, "node_modules/@aws-sdk/hash-node/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/hash-stream-node": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-stream-node/-/hash-stream-node-3.257.0.tgz", + "integrity": "sha512-A24+EI0sO+IYO78sQPY4vVx7vzToc6XAobQqowmBJ6GXXILK72d3MR3NVbm0lmcS4Dh6MVZEFQD/DCyKvj2C7g==", "dependencies": { "@aws-sdk/types": "3.257.0", "@aws-sdk/util-utf8": "3.254.0", @@ -3259,11 +3358,13 @@ }, "node_modules/@aws-sdk/hash-stream-node/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/invalid-dependency": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.257.0.tgz", + "integrity": "sha512-T68SAPRNMEhpke0wlxURgogL7q0B8dfqZsSeS20BVR/lksJxLse9+pbmCDxiu1RrXoEIsEwl5rbLN+Hw8BFFYw==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3271,11 +3372,13 @@ }, "node_modules/@aws-sdk/invalid-dependency/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/is-array-buffer": { "version": "3.201.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz", + "integrity": "sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg==", "dependencies": { "tslib": "^2.3.1" }, @@ -3285,11 +3388,13 @@ }, "node_modules/@aws-sdk/is-array-buffer/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/md5-js": { "version": "3.258.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.258.0.tgz", + "integrity": "sha512-aLdZ43sEiT68p7YYPHwKsWU1WDC8Wf8UQfb4pzbvhYNgr5VxN46AtbWTKxLAqK2adKS4FnbyX2i66fINg2dHdw==", "dependencies": { "@aws-sdk/types": "3.257.0", "@aws-sdk/util-utf8": "3.254.0", @@ -3298,11 +3403,13 @@ }, "node_modules/@aws-sdk/md5-js/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.259.0.tgz", + "integrity": "sha512-eY4Bf7ZeiYK2c2XQ5IU0TDneEYSnZbaFk+ysgAkNmGoLKBhybXiKy7Dh8djB3uXeNtsZ+fZaazWmsU2kxf6Ntg==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3316,11 +3423,13 @@ }, "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-content-length": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.257.0.tgz", + "integrity": "sha512-yiawbV2azm6QnMY1L2ypG8PDRdjOcEIvFmT0T7y0F49rfbKJOu21j1ONAoCkLrINK6kMqcD5JSQLVCoURxiTxQ==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3332,11 +3441,13 @@ }, "node_modules/@aws-sdk/middleware-content-length/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-endpoint": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.257.0.tgz", + "integrity": "sha512-RQNQe/jeVuWZtXXfcOm+e3qMFICY6ERsXUrbt0rjHgvajZCklcrRJgxJSCwrcS7Le3nl9azFPMAMj9L7uSK28g==", "dependencies": { "@aws-sdk/middleware-serde": "3.257.0", "@aws-sdk/protocol-http": "3.257.0", @@ -3353,11 +3464,13 @@ }, "node_modules/@aws-sdk/middleware-endpoint/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-expect-continue": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.257.0.tgz", + "integrity": "sha512-7HSRA2Ta0fTq9Ewznp6fYG7CYOoqr5TeqEhKL1HyFb5i6YmsCiz88JKNJTllD5O7uFcd7Td/fJ66pK4JttfaaQ==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3369,11 +3482,13 @@ }, "node_modules/@aws-sdk/middleware-expect-continue/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-flexible-checksums": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.259.0.tgz", + "integrity": "sha512-DwY3+cWaONvzJSVYQncfX+ZnoPnLVA7LfgR0mrgcvVZJFrqCr1lJeUmJOmE2/kcOQefPfSbKB/L4BP6vg2EUMQ==", "dependencies": { "@aws-crypto/crc32": "3.0.0", "@aws-crypto/crc32c": "3.0.0", @@ -3389,11 +3504,13 @@ }, "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-host-header": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.257.0.tgz", + "integrity": "sha512-gEi9AJdJfRfU8Qr6HK1hfhxTzyV3Giq4B/h7um99hIFAT/GCg9xiPvAOKPo6UeuiKEv3b7RpSL4s6cBvnJMJBA==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3405,11 +3522,13 @@ }, "node_modules/@aws-sdk/middleware-host-header/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-location-constraint": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.257.0.tgz", + "integrity": "sha512-pmm5rJR5aatXG0kC0KPBxkgoNn/ePcyVIYHGMEuJXRJm3ENy569QAH9UZeMFjprp3uuAbkqItQbY3MP8TYvuYA==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3420,11 +3539,13 @@ }, "node_modules/@aws-sdk/middleware-location-constraint/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-logger": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.257.0.tgz", + "integrity": "sha512-8RDXW/VbMKBsXDfcCLmROZcWKyrekyiPa3J1aIaBy0tq9o4xpGoXw/lwwIrNVvISAFslb57rteup34bfn6ta6w==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3435,11 +3556,13 @@ }, "node_modules/@aws-sdk/middleware-logger/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-recursion-detection": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.257.0.tgz", + "integrity": "sha512-rUCih6zHh8k9Edf5N5Er4s508FYbwLM0MWTD2axzlj9TjLqEQ9OKED3wHaLffXSDzodd3oTAfJCLPbWQyoZ3ZQ==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3451,11 +3574,13 @@ }, "node_modules/@aws-sdk/middleware-recursion-detection/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-retry": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.259.0.tgz", + "integrity": "sha512-pVh1g8e84MAi7eVtWLiiiCtn82LzxOP7+LxTRHatmgIeN22yGQBZILliPDJypUPvDYlwxI1ekiK+oPTcte0Uww==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/service-error-classification": "3.257.0", @@ -3471,18 +3596,21 @@ }, "node_modules/@aws-sdk/middleware-retry/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-retry/node_modules/uuid": { "version": "8.3.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/@aws-sdk/middleware-sdk-s3": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.257.0.tgz", + "integrity": "sha512-l9KRlUgsDKV1MB3zfttX/syhIBsG5Z3VVslz6EW09eSqZVreCudW3TMdyeLemup57xC2veEpkgVj8igiXd/LVQ==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3495,11 +3623,13 @@ }, "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-sdk-sts": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.257.0.tgz", + "integrity": "sha512-d6IJCLRi3O2tm4AFK60WNhIwmMmspj1WzKR1q1TaoPzoREPG2xg+Am18wZBRkCyYuRPPrbizmkvAmAJiUolMAw==", "dependencies": { "@aws-sdk/middleware-signing": "3.257.0", "@aws-sdk/property-provider": "3.257.0", @@ -3514,11 +3644,13 @@ }, "node_modules/@aws-sdk/middleware-sdk-sts/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-serde": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.257.0.tgz", + "integrity": "sha512-/JasfXPWFq24mnCrx9fxW/ISBSp07RJwhsF14qzm8Qy3Z0z470C+QRM6otTwAkYuuVt1wuLjja5agq3Jtzq7dQ==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3529,11 +3661,13 @@ }, "node_modules/@aws-sdk/middleware-serde/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-signing": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.257.0.tgz", + "integrity": "sha512-hCH3D83LHmm6nqmtNrGTWZCVjsQXrGHIXbd17/qrw7aPFvcAhsiiCncGFP+XsUXEKa2ZqcSNMUyPrx69ofNRZQ==", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/protocol-http": "3.257.0", @@ -3548,11 +3682,13 @@ }, "node_modules/@aws-sdk/middleware-signing/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-ssec": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.257.0.tgz", + "integrity": "sha512-YcZrKeZk/0bsFvnTqp2rcF+6BSmeLTA65ZtyNNP2hh7Imaxg3kAQcueOJBeK4YP/5nU7a1mtt/4Q8BqbIjc41g==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3563,11 +3699,13 @@ }, "node_modules/@aws-sdk/middleware-ssec/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-stack": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.257.0.tgz", + "integrity": "sha512-awg2F0SvwACBaw4HIObK8pQGfSqAc4Vy+YFzWSfZNVC35oRO6RsRdKHVU99lRC0LrT2Ptmfghl2DMPSrRDbvlQ==", "dependencies": { "tslib": "^2.3.1" }, @@ -3577,11 +3715,13 @@ }, "node_modules/@aws-sdk/middleware-stack/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/middleware-user-agent": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.257.0.tgz", + "integrity": "sha512-37rt75LZyD0UWpbcFuxEGqwF3DZKSixQPl7AsDe6q3KtrO5gGQB+diH5vbY0txNNYyv5IK9WMwvY73mVmoWRmw==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3593,11 +3733,13 @@ }, "node_modules/@aws-sdk/middleware-user-agent/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/node-config-provider": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.259.0.tgz", + "integrity": "sha512-DUOqr71oonBvM6yKPdhDBmraqgXHCFrVWFw7hc5ZNxL2wS/EsbKfGPJp+C+SUgpn1upIWPNnh/bNoLAbBkcLsA==", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/shared-ini-file-loader": "3.257.0", @@ -3610,11 +3752,13 @@ }, "node_modules/@aws-sdk/node-config-provider/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/node-http-handler": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.257.0.tgz", + "integrity": "sha512-8KnWHVVwaGKyTlkTU9BSOAiSovNDoagxemU2l10QqBbzUCVpljCUMUkABEGRJ1yoQCl6DJ7RtNkAyZ8Ne/E15A==", "dependencies": { "@aws-sdk/abort-controller": "3.257.0", "@aws-sdk/protocol-http": "3.257.0", @@ -3628,11 +3772,13 @@ }, "node_modules/@aws-sdk/node-http-handler/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/property-provider": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.257.0.tgz", + "integrity": "sha512-3rUbRAcF0GZ5PhDiXhS4yREfZ5hOEtvYEa9S/19OdM5eoypOaLU5XnFcCKfnccSP8SkdgpJujzxOMRWNWadlAQ==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3643,11 +3789,13 @@ }, "node_modules/@aws-sdk/property-provider/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/protocol-http": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.257.0.tgz", + "integrity": "sha512-xt7LGOgZIvbLS3418AYQLacOqx+mo5j4mPiIMz7f6AaUg+/fBUgESVsncKDqxbEJVwwCXSka8Ca0cntJmoeMSw==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3658,11 +3806,13 @@ }, "node_modules/@aws-sdk/protocol-http/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/querystring-builder": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.257.0.tgz", + "integrity": "sha512-mZHWLP7XIkzx1GIXO5WfX/iJ+aY9TWs02RE9FkdL2+by0HEMR65L3brQTbU1mIBJ7BjaPwYH24dljUOSABX7yg==", "dependencies": { "@aws-sdk/types": "3.257.0", "@aws-sdk/util-uri-escape": "3.201.0", @@ -3674,11 +3824,13 @@ }, "node_modules/@aws-sdk/querystring-builder/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/querystring-parser": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.257.0.tgz", + "integrity": "sha512-UDrE1dEwWrWT8dG2VCrGYrPxCWOkZ1fPTPkjpkR4KZEdQDZBqU5gYZF2xPj8Nz7pjQVHFuW2wFm3XYEk56GEjg==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3689,18 +3841,21 @@ }, "node_modules/@aws-sdk/querystring-parser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/service-error-classification": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.257.0.tgz", + "integrity": "sha512-FAyR0XsueGkkqDtkP03cTJQk52NdQ9sZelLynmmlGPUP75LApRPvFe1riKrou6+LsDbwVNVffj6mbDfIcOhaOw==", "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/shared-ini-file-loader": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.257.0.tgz", + "integrity": "sha512-HNjC1+Wx3xHiJc+CP14GhIdVhfQGSjroAsWseRxAhONocA9Fl1ZX4hx7+sA5c9nOoMVOovi6ivJ/6lCRPTDRrQ==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3711,11 +3866,13 @@ }, "node_modules/@aws-sdk/shared-ini-file-loader/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/signature-v4": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.257.0.tgz", + "integrity": "sha512-aLQQN59X/D0+ShzPD3Anj5ntdMA/RFeNLOUCDyDvremViGi6yxUS98usQ/8bG5Rq0sW2GGMdbFUFmrDvqdiqEQ==", "dependencies": { "@aws-sdk/is-array-buffer": "3.201.0", "@aws-sdk/types": "3.257.0", @@ -3731,7 +3888,8 @@ }, "node_modules/@aws-sdk/signature-v4-multi-region": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.257.0.tgz", + "integrity": "sha512-4ZyJp6my6F6R8jG+zlIR+Sw3W2vZcBTcpzAnSAHI0UBWjx5/buiKU5QY7oj29H3pESDD7DovZinD7TtHvMNoZw==", "dependencies": { "@aws-sdk/protocol-http": "3.257.0", "@aws-sdk/signature-v4": "3.257.0", @@ -3753,15 +3911,18 @@ }, "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/signature-v4/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/smithy-client": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.257.0.tgz", + "integrity": "sha512-Vy/en+llpslHG6WZ2yuN+On6u7p2hROEURwAST/lpReAwBETjbsxylkWvP8maeGKQ54u9uC6lIZAOJut2I3INw==", "dependencies": { "@aws-sdk/middleware-stack": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3773,11 +3934,13 @@ }, "node_modules/@aws-sdk/smithy-client/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/token-providers": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.259.0.tgz", + "integrity": "sha512-61lbk+vjlHBtNK7ZOTdR0rgk9dQ6++tklHpXZY3AQWAl3xx6K4y00HsyAtcP6k24s8B356QwXlrQJrQY5nnkQQ==", "dependencies": { "@aws-sdk/client-sso-oidc": "3.259.0", "@aws-sdk/property-provider": "3.257.0", @@ -3791,11 +3954,13 @@ }, "node_modules/@aws-sdk/token-providers/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/types": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.257.0.tgz", + "integrity": "sha512-LmqXuBQBGeaGi/3Rp7XiEX1B5IPO2UUfBVvu0wwGqVsmstT0SbOVDZGPmxygACbm64n+PRx3uTSDefRfoiWYZg==", "dependencies": { "tslib": "^2.3.1" }, @@ -3805,11 +3970,13 @@ }, "node_modules/@aws-sdk/types/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/url-parser": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.257.0.tgz", + "integrity": "sha512-Qe/AcFe/NFZHa6cN2afXEQn9ehXxh57dWGdRjfjd2lQqNV4WW1R2pl2Tm1ZJ1dwuCNLJi4NHLMk8lrD3QQ8rdg==", "dependencies": { "@aws-sdk/querystring-parser": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3818,11 +3985,13 @@ }, "node_modules/@aws-sdk/url-parser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-arn-parser": { "version": "3.208.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.208.0.tgz", + "integrity": "sha512-QV4af+kscova9dv4VuHOgH8wEr/IIYHDGcnyVtkUEqahCejWr1Kuk+SBK0xMwnZY5LSycOtQ8aeqHOn9qOjZtA==", "dependencies": { "tslib": "^2.3.1" }, @@ -3832,11 +4001,13 @@ }, "node_modules/@aws-sdk/util-arn-parser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-base64": { "version": "3.208.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz", + "integrity": "sha512-PQniZph5A6N7uuEOQi+1hnMz/FSOK/8kMFyFO+4DgA1dZ5pcKcn5wiFwHkcTb/BsgVqQa3Jx0VHNnvhlS8JyTg==", "dependencies": { "@aws-sdk/util-buffer-from": "3.208.0", "tslib": "^2.3.1" @@ -3847,22 +4018,26 @@ }, "node_modules/@aws-sdk/util-base64/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-body-length-browser": { "version": "3.188.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz", + "integrity": "sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==", "dependencies": { "tslib": "^2.3.1" } }, "node_modules/@aws-sdk/util-body-length-browser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-body-length-node": { "version": "3.208.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz", + "integrity": "sha512-3zj50e5g7t/MQf53SsuuSf0hEELzMtD8RX8C76f12OSRo2Bca4FLLYHe0TZbxcfQHom8/hOaeZEyTyMogMglqg==", "dependencies": { "tslib": "^2.3.1" }, @@ -3872,11 +4047,13 @@ }, "node_modules/@aws-sdk/util-body-length-node/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-buffer-from": { "version": "3.208.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz", + "integrity": "sha512-7L0XUixNEFcLUGPeBF35enCvB9Xl+K6SQsmbrPk1P3mlV9mguWSDQqbOBwY1Ir0OVbD6H/ZOQU7hI/9RtRI0Zw==", "dependencies": { "@aws-sdk/is-array-buffer": "3.201.0", "tslib": "^2.3.1" @@ -3887,11 +4064,13 @@ }, "node_modules/@aws-sdk/util-buffer-from/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-config-provider": { "version": "3.208.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz", + "integrity": "sha512-DSRqwrERUsT34ug+anlMBIFooBEGwM8GejC7q00Y/9IPrQy50KnG5PW2NiTjuLKNi7pdEOlwTSEocJE15eDZIg==", "dependencies": { "tslib": "^2.3.1" }, @@ -3901,11 +4080,13 @@ }, "node_modules/@aws-sdk/util-config-provider/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-defaults-mode-browser": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.257.0.tgz", + "integrity": "sha512-nkfK+MNacVd3Px/fcAvU0hDeh+r7d+RLLt3sJ5Zc0gGd+i3OQEP58V8QzR9PYMvUvSvGQP16fQVQHSbRZtuWyQ==", "dependencies": { "@aws-sdk/property-provider": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -3918,11 +4099,13 @@ }, "node_modules/@aws-sdk/util-defaults-mode-browser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-defaults-mode-node": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.259.0.tgz", + "integrity": "sha512-wRiiwT7ayIcTYGHUg/Ho9UN/Kd4V37OAxP2IbkG9rPZJNuvtKopQJhUSMDERXaMQ47dG5US8G4YVYJIEO4cKgw==", "dependencies": { "@aws-sdk/config-resolver": "3.259.0", "@aws-sdk/credential-provider-imds": "3.259.0", @@ -3937,11 +4120,13 @@ }, "node_modules/@aws-sdk/util-defaults-mode-node/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-endpoints": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.257.0.tgz", + "integrity": "sha512-3bvmRn5XGYzPPWjLuvHBKdJOb+fijnb8Ungu9bfXnTYFsng/ndHUWeHC22O/p8w3OWoRYUIMaZHxdxe27BFozg==", "dependencies": { "@aws-sdk/types": "3.257.0", "tslib": "^2.3.1" @@ -3952,11 +4137,13 @@ }, "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-hex-encoding": { "version": "3.201.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz", + "integrity": "sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA==", "dependencies": { "tslib": "^2.3.1" }, @@ -3966,11 +4153,13 @@ }, "node_modules/@aws-sdk/util-hex-encoding/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-locate-window": { "version": "3.208.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.208.0.tgz", + "integrity": "sha512-iua1A2+P7JJEDHVgvXrRJSvsnzG7stYSGQnBVphIUlemwl6nN5D+QrgbjECtrbxRz8asYFHSzhdhECqN+tFiBg==", "dependencies": { "tslib": "^2.3.1" }, @@ -3980,11 +4169,13 @@ }, "node_modules/@aws-sdk/util-locate-window/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-middleware": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.257.0.tgz", + "integrity": "sha512-F9ieon8B8eGVs5tyZtAIG3DZEObDvujkspho0qRbUTHUosM0ylJLsMU800fmC/uRHLRrZvb/RSp59+kNDwSAMw==", "dependencies": { "tslib": "^2.3.1" }, @@ -3994,11 +4185,13 @@ }, "node_modules/@aws-sdk/util-middleware/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-retry": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.257.0.tgz", + "integrity": "sha512-l9TOsOAYtZxwW3q5fQKW4rsD9t2HVaBfQ4zBamHkNTfB4vBVvCnz4oxkvSvA2MlxCA6am+K1K/oj917Tpqk53g==", "dependencies": { "@aws-sdk/service-error-classification": "3.257.0", "tslib": "^2.3.1" @@ -4009,11 +4202,13 @@ }, "node_modules/@aws-sdk/util-retry/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-stream-browser": { "version": "3.258.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-stream-browser/-/util-stream-browser-3.258.0.tgz", + "integrity": "sha512-MCAxHL3Hz/+eU4LZk0ZbLWAIUueH/jHpSbrloxZ3Dil2RL3w6NSJd5gE8zS7gs1B/eMcE600Brf5xSDR8kA5HA==", "dependencies": { "@aws-sdk/fetch-http-handler": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4025,11 +4220,13 @@ }, "node_modules/@aws-sdk/util-stream-browser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-stream-node": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-stream-node/-/util-stream-node-3.257.0.tgz", + "integrity": "sha512-UlLEerQCNejNulYmGXm/4X463n8n21foA2d6kgJ4AUSMWWhoRBjfwrM4gI7tA30zh9U81d6xbUtoOQTqKVtMTw==", "dependencies": { "@aws-sdk/node-http-handler": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4042,11 +4239,13 @@ }, "node_modules/@aws-sdk/util-stream-node/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-uri-escape": { "version": "3.201.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz", + "integrity": "sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA==", "dependencies": { "tslib": "^2.3.1" }, @@ -4056,11 +4255,13 @@ }, "node_modules/@aws-sdk/util-uri-escape/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-user-agent-browser": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.257.0.tgz", + "integrity": "sha512-YdavWK6/8Cw6mypEgysGGX/dT9p9qnzFbnN5PQsUY+JJk2Nx8fKFydjGiQ+6rWPeW17RAv9mmbboh9uPVWxVlw==", "dependencies": { "@aws-sdk/types": "3.257.0", "bowser": "^2.11.0", @@ -4069,11 +4270,13 @@ }, "node_modules/@aws-sdk/util-user-agent-browser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-user-agent-node": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.259.0.tgz", + "integrity": "sha512-R0VTmNs+ySDDebU98BUbsLyeIM5YmAEr9esPpy15XfSy3AWmAeru8nLlztdaLilHZzLIDzvM2t7NGk/FzZFCvA==", "dependencies": { "@aws-sdk/node-config-provider": "3.259.0", "@aws-sdk/types": "3.257.0", @@ -4093,11 +4296,13 @@ }, "node_modules/@aws-sdk/util-user-agent-node/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-utf8": { "version": "3.254.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.254.0.tgz", + "integrity": "sha512-14Kso/eIt5/qfIBmhEL9L1IfyUqswjSTqO2mY7KOzUZ9SZbwn3rpxmtkhmATkRjD7XIlLKaxBkI7tU9Zjzj8Kw==", "dependencies": { "@aws-sdk/util-buffer-from": "3.208.0", "tslib": "^2.3.1" @@ -4108,22 +4313,26 @@ }, "node_modules/@aws-sdk/util-utf8-browser": { "version": "3.259.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", "dependencies": { "tslib": "^2.3.1" } }, "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-utf8/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/util-waiter": { "version": "3.257.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.257.0.tgz", + "integrity": "sha512-Fr6of3EDOcXVDs5534o7VsJMXdybB0uLy2LzeFAVSwGOY3geKhIquBAiUDqCVu9B+iTldrC0rQ9NIM7ZSpPG8w==", "dependencies": { "@aws-sdk/abort-controller": "3.257.0", "@aws-sdk/types": "3.257.0", @@ -4135,11 +4344,13 @@ }, "node_modules/@aws-sdk/util-waiter/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@aws-sdk/xml-builder": { "version": "3.201.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.201.0.tgz", + "integrity": "sha512-brRdB1wwMgjWEnOQsv7zSUhIQuh7DEicrfslAqHop4S4FtSI3GQAShpQqgOpMTNFYcpaWKmE/Y1MJmNY7xLCnw==", "dependencies": { "tslib": "^2.3.1" }, @@ -4149,7 +4360,8 @@ }, "node_modules/@aws-sdk/xml-builder/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/@babel/code-frame": { "version": "7.24.2", @@ -4450,7 +4662,8 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.20.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "engines": { "node": ">=6.9.0" } @@ -5000,7 +5213,8 @@ }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.18.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.18.6" }, @@ -6058,7 +6272,8 @@ }, "node_modules/@dotcom-reliability-kit/app-info": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/app-info/-/app-info-2.1.0.tgz", + "integrity": "sha512-u7QicgkUbN58IMywvXmNuXxMK5bHUKfjeDC6s3u7TQg5uTGNicdrpBb8zB2O5K++g5KIlVnAafPcJct3ct9Nfw==", "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x" @@ -6066,7 +6281,8 @@ }, "node_modules/@dotcom-reliability-kit/crash-handler": { "version": "3.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/crash-handler/-/crash-handler-3.0.2.tgz", + "integrity": "sha512-+o8gfHC4B4RkqEThoiPU29qVeSlmJQ96sr6KDtoSVXg/J03QRK0mnYgvNsY0AonxyIdgZPD9Tteq6tDomTNP1A==", "dependencies": { "@dotcom-reliability-kit/log-error": "^3.1.0" }, @@ -6077,8 +6293,9 @@ }, "node_modules/@dotcom-reliability-kit/eslint-config": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/eslint-config/-/eslint-config-2.0.0.tgz", + "integrity": "sha512-h9v1nZ4FRe2iHVm53QGoq4BafbQOWhtb0b/Kuxd3ed+HMvYn/ft8A/Av/Xg8vAnJ7uoJspWgkt8qxgDnwX5vxg==", "dev": true, - "license": "MIT", "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x" @@ -6089,7 +6306,8 @@ }, "node_modules/@dotcom-reliability-kit/log-error": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/log-error/-/log-error-3.1.0.tgz", + "integrity": "sha512-1HAjOQuNXZQkyIQ3A+i0SFUylFMKF+R4sx923RN2NU9DA+f3S4F7Yd+L7ty36ocZJL1YYrUjtcr2Yx9IC+hh7g==", "dependencies": { "@dotcom-reliability-kit/app-info": "^2.1.0", "@dotcom-reliability-kit/logger": "^2.2.9", @@ -6103,7 +6321,8 @@ }, "node_modules/@dotcom-reliability-kit/logger": { "version": "2.2.9", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/logger/-/logger-2.2.9.tgz", + "integrity": "sha512-+3KSEdsypnz54VMgSVXnjyXTeJ5ZfyHF4jU3tcNcDrouGHT+JpD1ERkypfRfidwRRGtGup4FC2kjczpPGmecsw==", "dependencies": { "@dotcom-reliability-kit/app-info": "^2.1.0", "@dotcom-reliability-kit/serialize-error": "^2.1.0", @@ -6120,7 +6339,8 @@ }, "node_modules/@dotcom-reliability-kit/serialize-error": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-JYgnyvds/FZ0KJVRtOAsk9skue5i/vDBkRvQQg5Q/xlbwLdeUSAtD3XXBtlaohHov8kY7/I9UaXcoG6zXZ3a5Q==", "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x" @@ -6128,7 +6348,8 @@ }, "node_modules/@dotcom-reliability-kit/serialize-request": { "version": "2.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@dotcom-reliability-kit/serialize-request/-/serialize-request-2.2.0.tgz", + "integrity": "sha512-jM8GWWFzBFAXVkv1PPssAFC7mZLoEac9LV5HIINKmhxxe+av3eXJH53MwNQUARMqrIA3Hm7D7khT4L5gnuGcDg==", "engines": { "node": "16.x || 18.x || 20.x", "npm": "7.x || 8.x || 9.x" @@ -6234,10 +6455,6 @@ "resolved": "plugins/mocha", "link": true }, - "node_modules/@dotcom-tool-kit/monorepo": { - "resolved": "plugins/monorepo", - "link": true - }, "node_modules/@dotcom-tool-kit/n-test": { "resolved": "plugins/n-test", "link": true @@ -6278,52 +6495,405 @@ "resolved": "plugins/prettier", "link": true }, - "node_modules/@dotcom-tool-kit/schemas": { - "resolved": "lib/schemas", - "link": true + "node_modules/@dotcom-tool-kit/schemas": { + "resolved": "lib/schemas", + "link": true + }, + "node_modules/@dotcom-tool-kit/serverless": { + "resolved": "plugins/serverless", + "link": true + }, + "node_modules/@dotcom-tool-kit/state": { + "resolved": "lib/state", + "link": true + }, + "node_modules/@dotcom-tool-kit/typescript": { + "resolved": "plugins/typescript", + "link": true + }, + "node_modules/@dotcom-tool-kit/upload-assets-to-s3": { + "resolved": "plugins/upload-assets-to-s3", + "link": true + }, + "node_modules/@dotcom-tool-kit/validated": { + "resolved": "lib/validated", + "link": true + }, + "node_modules/@dotcom-tool-kit/vault": { + "resolved": "lib/vault", + "link": true + }, + "node_modules/@dotcom-tool-kit/wait-for-ok": { + "resolved": "lib/wait-for-ok", + "link": true + }, + "node_modules/@dotcom-tool-kit/webpack": { + "resolved": "plugins/webpack", + "link": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@dotcom-tool-kit/serverless": { - "resolved": "plugins/serverless", - "link": true + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@dotcom-tool-kit/state": { - "resolved": "lib/state", - "link": true + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@dotcom-tool-kit/typescript": { - "resolved": "plugins/typescript", - "link": true + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@dotcom-tool-kit/upload-assets-to-s3": { - "resolved": "plugins/upload-assets-to-s3", - "link": true + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@dotcom-tool-kit/validated": { - "resolved": "lib/validated", - "link": true + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@dotcom-tool-kit/vault": { - "resolved": "lib/vault", - "link": true + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@dotcom-tool-kit/wait-for-ok": { - "resolved": "lib/wait-for-ok", - "link": true + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@dotcom-tool-kit/webpack": { - "resolved": "plugins/webpack", - "link": true + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/@esbuild/darwin-arm64": { + "node_modules/@esbuild/win32-x64": { "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", "cpu": [ - "arm64" + "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { "node": ">=12" @@ -6331,8 +6901,9 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -6345,8 +6916,9 @@ }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -6356,16 +6928,18 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", + "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", "dev": true, - "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", + "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -6386,17 +6960,19 @@ }, "node_modules/@eslint/js": { "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", + "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", "dev": true, - "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@financial-times/eslint-config-next": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@financial-times/eslint-config-next/-/eslint-config-next-6.0.0.tgz", + "integrity": "sha512-8zQ4c4I11CTahJx4MI/WWT/xKSqubRAlHm37IyrqrO9KSA9+KB6iyMj5vF8WttxNB1M8sIWHTgqZwoJmgnHhxQ==", "dev": true, "hasInstallScript": true, - "license": "MIT", "dependencies": { "eslint": ">=5.0.0", "eslint-plugin-no-only-tests": ">=2.0.0" @@ -6406,6 +6982,20 @@ "npm": "7.x || 8.x" } }, + "node_modules/@financial-times/n-fetch": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@financial-times/n-fetch/-/n-fetch-1.0.0.tgz", + "integrity": "sha512-6ayYnrlSJZvGU8/ZJEskxYH2kdvwJU/aL9MSXc3FmPj3dft7ecMxsB4p8PsWeJamHyd8EjaL7Mwm63LR2DwePg==", + "dependencies": { + "@dotcom-reliability-kit/logger": "^2.2.7", + "http-errors": "^1.6.1", + "node-fetch": "^2.0.0" + }, + "engines": { + "node": "16.x || 18.x", + "npm": "7.x || 8.x || 9.x" + } + }, "node_modules/@financial-times/package-json": { "version": "3.0.0", "license": "MIT" @@ -6416,8 +7006,9 @@ }, "node_modules/@google-automations/git-file-utils": { "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@google-automations/git-file-utils/-/git-file-utils-1.2.3.tgz", + "integrity": "sha512-CdxeRDIExWMdMIhRNbbqI3amtF72jct3XVEKquqinkSbUbzYx+ZxvakCwJB0FDS8xmq9mjEWEt0Cxy/+49A8kw==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@octokit/rest": "19.0.5", "@octokit/types": "^8.0.0", @@ -6429,29 +7020,33 @@ }, "node_modules/@google-automations/git-file-utils/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", + "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", + "dev": true }, "node_modules/@google-automations/git-file-utils/node_modules/@octokit/types": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", + "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } }, "node_modules/@google-automations/git-file-utils/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@google-automations/git-file-utils/node_modules/minimatch": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -6461,7 +7056,8 @@ }, "node_modules/@hapi/accept": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-6.0.0.tgz", + "integrity": "sha512-aG/Ml4kSBWCVmWvR8N8ULRuB385D8K/3OI7lquZQruH11eM7sHR5Nha30BbDzijJHtyV7Vwc6MlMwNfwb70ISg==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6470,7 +7066,8 @@ }, "node_modules/@hapi/ammo": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/ammo/-/ammo-6.0.0.tgz", + "integrity": "sha512-lhX7SYtWScQaeAIL5XnE54WzyDgS5RXVeEtFEovyZcTdVzTYbo0nem56Bwko1PBcRxRUIw1v2tMb6sjFs6vEwg==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0" @@ -6478,7 +7075,8 @@ }, "node_modules/@hapi/b64": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/b64/-/b64-6.0.0.tgz", + "integrity": "sha512-Es6o4BtzvMmNF28KJGuwUzUtMjF6ToZ1hQt3UOjaXc6TNkRefel+NyQSjc9b5q3Re7xwv23r0xK3Vo3yreaJHQ==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0" @@ -6486,7 +7084,8 @@ }, "node_modules/@hapi/boom": { "version": "10.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-10.0.0.tgz", + "integrity": "sha512-1YVs9tLHhypBqqinKQRqh7FUERIolarQApO37OWkzD+z6y6USi871Sv746zBPKcIOBuI6g6y4FrwX87mmJ90Gg==", "peer": true, "dependencies": { "@hapi/hoek": "10.x.x" @@ -6494,7 +7093,8 @@ }, "node_modules/@hapi/bounce": { "version": "3.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/bounce/-/bounce-3.0.0.tgz", + "integrity": "sha512-L0G4NcwwOYRhpcXeL76hNrLTUcObqtZMB3z4kcRVUZcR/w3v6C5Q1cTElV4/V7og1fG+wOyDR55UMFA+tWfhtA==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6503,12 +7103,14 @@ }, "node_modules/@hapi/bourne": { "version": "3.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-3.0.0.tgz", + "integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==", "peer": true }, "node_modules/@hapi/call": { "version": "9.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/call/-/call-9.0.0.tgz", + "integrity": "sha512-Z6byqbEtKF3RIH2kWG6cX64RwEqHBWYEVkNoEx6oKvkPaTrC6WTPRgr+ANo9Xa8G1GXyvs/NCMTnn3Mdj12TSA==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6517,7 +7119,8 @@ }, "node_modules/@hapi/catbox": { "version": "12.1.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/catbox/-/catbox-12.1.0.tgz", + "integrity": "sha512-60MCN5lgaXcuRTjMZqLR+DV0clS5RAFAwfYAQU2/na6PqrXHDRQcJwVMwP7jJayCrJm4POJlLDzZLuh1ba5XUg==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6528,7 +7131,8 @@ }, "node_modules/@hapi/catbox-memory": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/catbox-memory/-/catbox-memory-6.0.0.tgz", + "integrity": "sha512-A1O30g8GdaODx/GinytF6jFm772pdTPVWJe0cF2RiTOfhgIAAagzCcpBqRgQ8olLui0F5bzUF/SAi4BmkZ4yxA==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6537,7 +7141,8 @@ }, "node_modules/@hapi/content": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/content/-/content-6.0.0.tgz", + "integrity": "sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0" @@ -6545,7 +7150,8 @@ }, "node_modules/@hapi/cryptiles": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/cryptiles/-/cryptiles-6.0.0.tgz", + "integrity": "sha512-CUypQJI2F3HaKZjwlky3KyLu7p0O4WJXNJj+2AZ0czqwkwQIz8j+btOkzA3OMar8WTntnCrDx0f92PzxEK+JlA==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0" @@ -6556,12 +7162,14 @@ }, "node_modules/@hapi/file": { "version": "3.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/file/-/file-3.0.0.tgz", + "integrity": "sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q==", "peer": true }, "node_modules/@hapi/h2o2": { "version": "10.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/h2o2/-/h2o2-10.0.0.tgz", + "integrity": "sha512-eY5uulCxtvN68xHCXt7dr7yQQrFgsQpCkBRsxbYjdkWCPl2PJBHktQGeXqrumz8XKR1RUmElqNZK2IjdUxK/gw==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6575,7 +7183,8 @@ }, "node_modules/@hapi/hapi": { "version": "21.2.1", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/hapi/-/hapi-21.2.1.tgz", + "integrity": "sha512-mDBhIi/zIYhWPaZF4Z8h7jUtWC3bz7xYuUyI5riXZV9DabFnNOKpQfOob6V5ZcDwEJfmnWHgJO37BVCn31BStQ==", "peer": true, "dependencies": { "@hapi/accept": "^6.0.0", @@ -6603,7 +7212,8 @@ }, "node_modules/@hapi/heavy": { "version": "8.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/heavy/-/heavy-8.0.0.tgz", + "integrity": "sha512-NpKo74mF66GSwYu31IZwp11/6NmaUYxHeMTKSky09XBs8fVbzQDP83856+l+Ji6wxGmUeg75itCu1ujvEF6mdA==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6613,12 +7223,14 @@ }, "node_modules/@hapi/hoek": { "version": "10.0.1", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-10.0.1.tgz", + "integrity": "sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw==", "peer": true }, "node_modules/@hapi/iron": { "version": "7.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/iron/-/iron-7.0.0.tgz", + "integrity": "sha512-NNXJP5fpeiTCPj/4OJG2PWBjWC0/V5D8YggS9RZeuBbfUUuTYE6TbdGqLUsCzIpPI54I8W5dhwEGbRv1CnWQtw==", "peer": true, "dependencies": { "@hapi/b64": "^6.0.0", @@ -6630,7 +7242,8 @@ }, "node_modules/@hapi/mimos": { "version": "7.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/mimos/-/mimos-7.0.0.tgz", + "integrity": "sha512-ALORTrZrrBPOUX05rW4htNajoekEjQtUi1PB+17/3xs/hkdQ+gSEFbs5GdJihA49qWf7td3v4PgnvOe8mcf/jQ==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -6639,7 +7252,8 @@ }, "node_modules/@hapi/nigel": { "version": "5.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/nigel/-/nigel-5.0.0.tgz", + "integrity": "sha512-I9eq43BnSdz1BkvMpG7mFL7J+SIfn6DLNThuxFpIOAMUnkWbPgtcFP+HHrBAeoFkowfgQrr02vsIAkAPml4hvw==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -6651,7 +7265,8 @@ }, "node_modules/@hapi/pez": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/pez/-/pez-6.0.0.tgz", + "integrity": "sha512-3bMmsvlqrVNqaNEe4JWLZVpJ40jXuQ3vDy1+fbhyJmuAdMCMCkWexsKc7fT+mu18pFIwJzlenjc4/VE3weTq7w==", "peer": true, "dependencies": { "@hapi/b64": "^6.0.0", @@ -6663,7 +7278,8 @@ }, "node_modules/@hapi/podium": { "version": "5.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/podium/-/podium-5.0.0.tgz", + "integrity": "sha512-SbhFdu8LOIscMS82Zsoj9abcllAqbK4qBgznzJ9yr+vS2j1EomJTukkhxb76Lml0BHCd4Hn79F+3EQg06kcf8g==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -6673,7 +7289,8 @@ }, "node_modules/@hapi/shot": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-6.0.0.tgz", + "integrity": "sha512-RLGgzXy9GciJDunhY40NbVnLgYqp5gfBooZ2fOkAr4KbCEav/SJtYQS1N+knR7WFGzy8aooCR3XBUPI4ghHAkQ==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -6682,7 +7299,8 @@ }, "node_modules/@hapi/somever": { "version": "4.1.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/somever/-/somever-4.1.0.tgz", + "integrity": "sha512-koNBYu7Jdcb7gaC4VcnU78rFxSlsYwuElm6NMznE0EEeznzJtvLLmDZX0SPX8kXWC/E7ONlE29HF/yiSOgWG1Q==", "peer": true, "dependencies": { "@hapi/bounce": "^3.0.0", @@ -6691,12 +7309,14 @@ }, "node_modules/@hapi/somever/node_modules/@hapi/hoek": { "version": "9.3.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", "peer": true }, "node_modules/@hapi/statehood": { "version": "8.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/statehood/-/statehood-8.0.0.tgz", + "integrity": "sha512-umQTPID7BwmqAv9Rx7yLtbTNzsYg4va96aLqKneb3mlBQG32uq4iOQZ6luwBVACDFhqU3C3ewhznhukN09ZkZQ==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6710,7 +7330,8 @@ }, "node_modules/@hapi/subtext": { "version": "8.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/subtext/-/subtext-8.0.0.tgz", + "integrity": "sha512-fD+LY1U1SIUNHZJrNMIbuGl3CAd9JN8slljarFO4b8RrifkzjqbvdlZu/6iT6zlNM35GtDExf7hIepbUFUkT7A==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6724,7 +7345,8 @@ }, "node_modules/@hapi/teamwork": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/teamwork/-/teamwork-6.0.0.tgz", + "integrity": "sha512-05HumSy3LWfXpmJ9cr6HzwhAavrHkJ1ZRCmNE2qJMihdM5YcWreWPfyN0yKT2ZjCM92au3ZkuodjBxOibxM67A==", "peer": true, "engines": { "node": ">=14.0.0" @@ -6732,7 +7354,8 @@ }, "node_modules/@hapi/topo": { "version": "6.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.0.tgz", + "integrity": "sha512-aorJvN1Q1n5xrZuA50Z4X6adI6VAM2NalIVm46ALL9LUvdoqhof3JPY69jdJH8asM3PsWr2SUVYzp57EqUP41A==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0" @@ -6740,7 +7363,8 @@ }, "node_modules/@hapi/validate": { "version": "2.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/validate/-/validate-2.0.0.tgz", + "integrity": "sha512-w5m8MvBgqGndbMIB+AWmXTb8CLtF1DlIxbnbAHNAo7aFuNQuI1Ywc2e0zDLK5fbFXDoqRzNrHnC7JjNJ+hDigw==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0", @@ -6749,7 +7373,8 @@ }, "node_modules/@hapi/vise": { "version": "5.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/vise/-/vise-5.0.0.tgz", + "integrity": "sha512-bz/PA7DHIvsd/2eoW7t9WpU8+k9pofZHppYEn1mCTOVnC/cGN3hCEYaoAe6BpoeJM72iJDKZEOWvQvfgCrmzxA==", "peer": true, "dependencies": { "@hapi/hoek": "^10.0.0" @@ -6757,7 +7382,8 @@ }, "node_modules/@hapi/wreck": { "version": "18.0.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/@hapi/wreck/-/wreck-18.0.0.tgz", + "integrity": "sha512-Yk9STxoM06Hjjq58cH0KFG91u9F2h9eVE72o8vUr3AfK80qt7I2POG5+cDGTEntbnvvzm0ERow2sjG3QsqCWUA==", "peer": true, "dependencies": { "@hapi/boom": "^10.0.0", @@ -6767,8 +7393,9 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", @@ -6780,8 +7407,9 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -6973,9 +7601,9 @@ } }, "node_modules/@jest/console/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/@jest/core": { "version": "29.7.0", @@ -7183,9 +7811,9 @@ } }, "node_modules/@jest/core/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/@jest/core/node_modules/ts-node": { "version": "10.9.2", @@ -7425,9 +8053,9 @@ } }, "node_modules/@jest/expect/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/@jest/fake-timers": { "version": "27.5.1", @@ -7632,9 +8260,9 @@ } }, "node_modules/@jest/reporters/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/@jest/reporters/node_modules/semver": { "version": "7.6.0", @@ -7811,7 +8439,8 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "engines": { "node": ">=6.0.0" } @@ -7826,7 +8455,8 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -7839,14 +8469,16 @@ }, "node_modules/@kwsites/file-exists": { "version": "1.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", "dependencies": { "debug": "^4.1.1" } }, "node_modules/@kwsites/promise-deferred": { "version": "1.1.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, "node_modules/@lerna/child-process": { "version": "4.0.0", @@ -8412,12 +9044,14 @@ }, "node_modules/@npm/types": { "version": "1.0.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@npm/types/-/types-1.0.2.tgz", + "integrity": "sha512-KXZccTDEnWqNrrx6JjpJKU/wJvNeg9BDgjS0XhmlZab7br921HtyVbsYzJr4L+xIvjdJ20Wh9dgxgCI2a5CEQw==", + "dev": true }, "node_modules/@npmcli/fs": { "version": "1.1.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -8487,7 +9121,9 @@ }, "node_modules/@npmcli/move-file": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -8498,18 +9134,21 @@ }, "node_modules/@npmcli/node-gyp": { "version": "1.0.3", - "license": "ISC" + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz", + "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==" }, "node_modules/@npmcli/promise-spawn": { "version": "1.3.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", + "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", "dependencies": { "infer-owner": "^1.0.4" } }, "node_modules/@npmcli/run-script": { "version": "2.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-2.0.0.tgz", + "integrity": "sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig==", "dependencies": { "@npmcli/node-gyp": "^1.0.2", "@npmcli/promise-spawn": "^1.3.2", @@ -8519,7 +9158,8 @@ }, "node_modules/@octokit/auth-token": { "version": "3.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.2.tgz", + "integrity": "sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==", "dependencies": { "@octokit/types": "^8.0.0" }, @@ -8529,18 +9169,21 @@ }, "node_modules/@octokit/auth-token/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", + "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" }, "node_modules/@octokit/auth-token/node_modules/@octokit/types": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", + "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dependencies": { "@octokit/openapi-types": "^14.0.0" } }, "node_modules/@octokit/core": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.1.0.tgz", + "integrity": "sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==", "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", @@ -8556,7 +9199,8 @@ }, "node_modules/@octokit/core/node_modules/@octokit/endpoint": { "version": "7.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", + "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", "dependencies": { "@octokit/types": "^8.0.0", "is-plain-object": "^5.0.0", @@ -8568,11 +9212,13 @@ }, "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", + "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" }, "node_modules/@octokit/core/node_modules/@octokit/request": { "version": "6.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", + "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -8587,7 +9233,8 @@ }, "node_modules/@octokit/core/node_modules/@octokit/request-error": { "version": "3.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", + "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", "dependencies": { "@octokit/types": "^8.0.0", "deprecation": "^2.0.0", @@ -8599,7 +9246,8 @@ }, "node_modules/@octokit/core/node_modules/@octokit/types": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", + "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dependencies": { "@octokit/openapi-types": "^14.0.0" } @@ -8615,7 +9263,8 @@ }, "node_modules/@octokit/graphql": { "version": "5.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.4.tgz", + "integrity": "sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==", "dependencies": { "@octokit/request": "^6.0.0", "@octokit/types": "^8.0.0", @@ -8627,7 +9276,8 @@ }, "node_modules/@octokit/graphql/node_modules/@octokit/endpoint": { "version": "7.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", + "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", "dependencies": { "@octokit/types": "^8.0.0", "is-plain-object": "^5.0.0", @@ -8639,11 +9289,13 @@ }, "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", + "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" }, "node_modules/@octokit/graphql/node_modules/@octokit/request": { "version": "6.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", + "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -8658,7 +9310,8 @@ }, "node_modules/@octokit/graphql/node_modules/@octokit/request-error": { "version": "3.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", + "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", "dependencies": { "@octokit/types": "^8.0.0", "deprecation": "^2.0.0", @@ -8670,7 +9323,8 @@ }, "node_modules/@octokit/graphql/node_modules/@octokit/types": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", + "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dependencies": { "@octokit/openapi-types": "^14.0.0" } @@ -8681,7 +9335,8 @@ }, "node_modules/@octokit/plugin-paginate-rest": { "version": "5.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz", + "integrity": "sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==", "dependencies": { "@octokit/types": "^8.0.0" }, @@ -8694,25 +9349,29 @@ }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", + "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", + "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dependencies": { "@octokit/openapi-types": "^14.0.0" } }, "node_modules/@octokit/plugin-request-log": { "version": "1.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", "peerDependencies": { "@octokit/core": ">=3" } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "6.7.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz", + "integrity": "sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==", "dependencies": { "@octokit/types": "^8.0.0", "deprecation": "^2.3.1" @@ -8726,11 +9385,13 @@ }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", + "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==" }, "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", + "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dependencies": { "@octokit/openapi-types": "^14.0.0" } @@ -8758,7 +9419,8 @@ }, "node_modules/@octokit/rest": { "version": "19.0.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.5.tgz", + "integrity": "sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==", "dependencies": { "@octokit/core": "^4.1.0", "@octokit/plugin-paginate-rest": "^5.0.0", @@ -8784,7 +9446,8 @@ }, "node_modules/@serverless/dashboard-plugin": { "version": "6.2.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@serverless/dashboard-plugin/-/dashboard-plugin-6.2.3.tgz", + "integrity": "sha512-iTZhpZbiVl6G2AyfgoqxemqqpG4pUceWys3GsyZtjimnfnGd2UFBOMVUMTavLhYia7lQc4kQVuXQ+afLlkg+pQ==", "peer": true, "dependencies": { "@serverless/event-mocks": "^1.1.1", @@ -8814,7 +9477,8 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/fs-extra": { "version": "9.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "peer": true, "dependencies": { "at-least-node": "^1.0.0", @@ -8828,7 +9492,8 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/is-wsl": { "version": "2.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "peer": true, "dependencies": { "is-docker": "^2.0.0" @@ -8839,7 +9504,8 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/lru-cache": { "version": "6.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "peer": true, "dependencies": { "yallist": "^4.0.0" @@ -8850,7 +9516,8 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/node-fetch": { "version": "2.6.9", - "license": "MIT", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", "peer": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -8869,7 +9536,8 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/open": { "version": "7.4.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "peer": true, "dependencies": { "is-docker": "^2.0.0", @@ -8884,7 +9552,8 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/semver": { "version": "7.3.8", - "license": "ISC", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "peer": true, "dependencies": { "lru-cache": "^6.0.0" @@ -8898,12 +9567,14 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/tr46": { "version": "0.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "peer": true }, "node_modules/@serverless/dashboard-plugin/node_modules/uuid": { "version": "8.3.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "peer": true, "bin": { "uuid": "dist/bin/uuid" @@ -8911,12 +9582,14 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/webidl-conversions": { "version": "3.0.1", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "peer": true }, "node_modules/@serverless/dashboard-plugin/node_modules/whatwg-url": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "peer": true, "dependencies": { "tr46": "~0.0.3", @@ -8925,12 +9598,14 @@ }, "node_modules/@serverless/dashboard-plugin/node_modules/yallist": { "version": "4.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "peer": true }, "node_modules/@serverless/event-mocks": { "version": "1.1.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/@serverless/event-mocks/-/event-mocks-1.1.1.tgz", + "integrity": "sha512-YAV5V/y+XIOfd+HEVeXfPWZb8C6QLruFk9tBivoX2roQLWVq145s4uxf8D0QioCueuRzkukHUS4JIj+KVoS34A==", "peer": true, "dependencies": { "@types/lodash": "^4.14.123", @@ -8939,7 +9614,8 @@ }, "node_modules/@serverless/platform-client": { "version": "4.3.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/@serverless/platform-client/-/platform-client-4.3.2.tgz", + "integrity": "sha512-DAa5Z0JAZc6UfrTZLYwqoZxgAponZpFwaqd7WzzMA+loMCkYWyJNwxrAmV6cr2UUJpkko4toPZuJ3vM9Ie+NDA==", "peer": true, "dependencies": { "adm-zip": "^0.5.5", @@ -8964,7 +9640,8 @@ }, "node_modules/@serverless/platform-client/node_modules/archiver": { "version": "5.3.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -8981,7 +9658,8 @@ }, "node_modules/@serverless/platform-client/node_modules/argparse": { "version": "1.0.10", - "license": "MIT", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "peer": true, "dependencies": { "sprintf-js": "~1.0.2" @@ -8989,7 +9667,8 @@ }, "node_modules/@serverless/platform-client/node_modules/compress-commons": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", @@ -9003,7 +9682,8 @@ }, "node_modules/@serverless/platform-client/node_modules/crc32-stream": { "version": "4.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", "peer": true, "dependencies": { "crc-32": "^1.2.0", @@ -9015,7 +9695,8 @@ }, "node_modules/@serverless/platform-client/node_modules/js-yaml": { "version": "3.14.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -9027,7 +9708,9 @@ }, "node_modules/@serverless/platform-client/node_modules/querystring": { "version": "0.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", "peer": true, "engines": { "node": ">=0.4.x" @@ -9035,12 +9718,14 @@ }, "node_modules/@serverless/platform-client/node_modules/throat": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", "peer": true }, "node_modules/@serverless/platform-client/node_modules/zip-stream": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -9053,7 +9738,8 @@ }, "node_modules/@serverless/utils": { "version": "6.8.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@serverless/utils/-/utils-6.8.2.tgz", + "integrity": "sha512-FW8zdG8OPoF6qgyutiMhz4m/5SxbQjoQdbaGcW3wU6xe3QzQh41Hif7I3Xuu4J62CvxiWuz19sxNDJz2mTcskw==", "peer": true, "dependencies": { "archive-type": "^4.0.0", @@ -9095,7 +9781,8 @@ }, "node_modules/@serverless/utils/node_modules/@sindresorhus/is": { "version": "4.6.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "peer": true, "engines": { "node": ">=10" @@ -9106,7 +9793,8 @@ }, "node_modules/@serverless/utils/node_modules/@szmarczak/http-timer": { "version": "4.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "peer": true, "dependencies": { "defer-to-connect": "^2.0.0" @@ -9117,7 +9805,8 @@ }, "node_modules/@serverless/utils/node_modules/cacheable-request": { "version": "7.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", "peer": true, "dependencies": { "clone-response": "^1.0.2", @@ -9134,7 +9823,8 @@ }, "node_modules/@serverless/utils/node_modules/cacheable-request/node_modules/get-stream": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "peer": true, "dependencies": { "pump": "^3.0.0" @@ -9148,13 +9838,14 @@ }, "node_modules/@serverless/utils/node_modules/ci-info": { "version": "3.7.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", + "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/sibiraj-s" } ], - "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -9162,7 +9853,8 @@ }, "node_modules/@serverless/utils/node_modules/decompress-response": { "version": "6.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "peer": true, "dependencies": { "mimic-response": "^3.1.0" @@ -9176,7 +9868,8 @@ }, "node_modules/@serverless/utils/node_modules/defer-to-connect": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "peer": true, "engines": { "node": ">=10" @@ -9184,7 +9877,8 @@ }, "node_modules/@serverless/utils/node_modules/got": { "version": "11.8.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "peer": true, "dependencies": { "@sindresorhus/is": "^4.0.0", @@ -9208,7 +9902,8 @@ }, "node_modules/@serverless/utils/node_modules/inquirer": { "version": "8.2.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", + "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", "peer": true, "dependencies": { "ansi-escapes": "^4.2.1", @@ -9233,17 +9928,20 @@ }, "node_modules/@serverless/utils/node_modules/json-buffer": { "version": "3.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "peer": true }, "node_modules/@serverless/utils/node_modules/jwt-decode": { "version": "3.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==", "peer": true }, "node_modules/@serverless/utils/node_modules/keyv": { "version": "4.5.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", "peer": true, "dependencies": { "json-buffer": "3.0.1" @@ -9251,7 +9949,8 @@ }, "node_modules/@serverless/utils/node_modules/lowercase-keys": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "peer": true, "engines": { "node": ">=8" @@ -9259,7 +9958,8 @@ }, "node_modules/@serverless/utils/node_modules/mimic-response": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "peer": true, "engines": { "node": ">=10" @@ -9270,7 +9970,8 @@ }, "node_modules/@serverless/utils/node_modules/normalize-url": { "version": "6.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "peer": true, "engines": { "node": ">=10" @@ -9281,7 +9982,8 @@ }, "node_modules/@serverless/utils/node_modules/p-cancelable": { "version": "2.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "peer": true, "engines": { "node": ">=8" @@ -9289,7 +9991,8 @@ }, "node_modules/@serverless/utils/node_modules/responselike": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", "peer": true, "dependencies": { "lowercase-keys": "^2.0.0" @@ -9300,7 +10003,8 @@ }, "node_modules/@serverless/utils/node_modules/supports-color": { "version": "8.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -9314,7 +10018,8 @@ }, "node_modules/@serverless/utils/node_modules/uuid": { "version": "8.3.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "peer": true, "bin": { "uuid": "dist/bin/uuid" @@ -9322,7 +10027,8 @@ }, "node_modules/@serverless/utils/node_modules/write-file-atomic": { "version": "4.0.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "peer": true, "dependencies": { "imurmurhash": "^0.1.4", @@ -9374,7 +10080,8 @@ }, "node_modules/@tokenizer/token": { "version": "0.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", "peer": true }, "node_modules/@tootallnate/once": { @@ -9401,8 +10108,9 @@ }, "node_modules/@tsconfig/node16": { "version": "1.0.3", - "devOptional": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "devOptional": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -9442,7 +10150,8 @@ }, "node_modules/@types/cacheable-request": { "version": "6.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", "peer": true, "dependencies": { "@types/http-cache-semantics": "*", @@ -9495,7 +10204,8 @@ }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", "peer": true }, "node_modules/@types/istanbul-lib-coverage": { @@ -9542,7 +10252,8 @@ }, "node_modules/@types/keyv": { "version": "3.1.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", "peer": true, "dependencies": { "@types/node": "*" @@ -9550,7 +10261,8 @@ }, "node_modules/@types/lodash": { "version": "4.14.189", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.189.tgz", + "integrity": "sha512-kb9/98N6X8gyME9Cf7YaqIMvYGnBSWqEci6tiettE6iJWH1XdJz/PO8LB0GtLCG7x8dU3KWhZT+lA1a35127tA==" }, "node_modules/@types/mime": { "version": "2.0.3", @@ -9574,12 +10286,14 @@ }, "node_modules/@types/node": { "version": "16.18.23", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.23.tgz", + "integrity": "sha512-XAMpaw1s1+6zM+jn2tmw8MyaRDIJfXxqmIQIS0HfoGYPuf7dUWeiUKopwq13KFX9lEp1+THGtlaaYx39Nxr58g==" }, "node_modules/@types/node-fetch": { "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*", "form-data": "^3.0.0" @@ -9691,7 +10405,8 @@ }, "node_modules/@types/responselike": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", "peer": true, "dependencies": { "@types/node": "*" @@ -9703,8 +10418,9 @@ }, "node_modules/@types/semver": { "version": "7.3.13", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true }, "node_modules/@types/ssri": { "version": "7.1.1", @@ -9728,8 +10444,9 @@ }, "node_modules/@types/temp": { "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@types/temp/-/temp-0.9.4.tgz", + "integrity": "sha512-+VfWIwrlept2VBTj7Y2wQnI/Xfscy1u8Pyj/puYwss6V1IblXn1x7S0S9eFh6KyBolgLCm+rUFzhFAbdkR691g==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*" } @@ -9761,7 +10478,8 @@ }, "node_modules/@types/yauzl": { "version": "2.10.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", "optional": true, "dependencies": { "@types/node": "*" @@ -9769,8 +10487,9 @@ }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.0.tgz", + "integrity": "sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.57.0", @@ -9802,8 +10521,9 @@ }, "node_modules/@typescript-eslint/parser": { "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.0.tgz", + "integrity": "sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "5.57.0", "@typescript-eslint/types": "5.57.0", @@ -9828,8 +10548,9 @@ }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz", + "integrity": "sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.57.0", "@typescript-eslint/visitor-keys": "5.57.0" @@ -9844,8 +10565,9 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.0.tgz", + "integrity": "sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/typescript-estree": "5.57.0", "@typescript-eslint/utils": "5.57.0", @@ -9870,8 +10592,9 @@ }, "node_modules/@typescript-eslint/types": { "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.0.tgz", + "integrity": "sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==", "dev": true, - "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -9882,8 +10605,9 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz", + "integrity": "sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "5.57.0", "@typescript-eslint/visitor-keys": "5.57.0", @@ -9908,8 +10632,9 @@ }, "node_modules/@typescript-eslint/utils": { "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.0.tgz", + "integrity": "sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", @@ -9933,8 +10658,9 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz", + "integrity": "sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==", "dev": true, - "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.57.0", "eslint-visitor-keys": "^3.3.0" @@ -9949,8 +10675,9 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -10198,8 +10925,9 @@ }, "node_modules/@xmldom/xmldom": { "version": "0.8.6", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz", + "integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==", "dev": true, - "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -10214,7 +10942,8 @@ }, "node_modules/2-thenable": { "version": "1.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/2-thenable/-/2-thenable-1.0.0.tgz", + "integrity": "sha512-HqiDzaLDFCXkcCO/SwoyhRwqYtINFHF7t9BDRq4x90TOKNAJpiqUt9X5lQ08bwxYzc067HUywDjGySpebHcUpw==", "peer": true, "dependencies": { "d": "1", @@ -10227,7 +10956,8 @@ }, "node_modules/abort-controller": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -10266,7 +10996,8 @@ }, "node_modules/adm-zip": { "version": "0.5.10", - "license": "MIT", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", "peer": true, "engines": { "node": ">=6.0" @@ -10328,7 +11059,8 @@ }, "node_modules/ajv-formats": { "version": "2.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "peer": true, "dependencies": { "ajv": "^8.0.0" @@ -10344,7 +11076,8 @@ }, "node_modules/ajv-formats/node_modules/ajv": { "version": "8.12.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -10359,7 +11092,8 @@ }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "peer": true }, "node_modules/ajv-keywords": { @@ -10418,7 +11152,8 @@ }, "node_modules/any-promise": { "version": "1.3.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "node_modules/anymatch": { "version": "3.1.2", @@ -10437,7 +11172,8 @@ }, "node_modules/archive-type": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==", "peer": true, "dependencies": { "file-type": "^4.2.0" @@ -10448,7 +11184,8 @@ }, "node_modules/archive-type/node_modules/file-type": { "version": "4.4.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==", "peer": true, "engines": { "node": ">=4" @@ -10559,7 +11296,8 @@ }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -10578,8 +11316,9 @@ }, "node_modules/array-includes": { "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -10596,7 +11335,8 @@ }, "node_modules/array-unflat-js": { "version": "0.1.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/array-unflat-js/-/array-unflat-js-0.1.3.tgz", + "integrity": "sha512-8pljkLj4vfz2i7Tf3yB31tRrszjP8/kwIyABGfcZ1GcHlvdUB0Sbx0WzQkOPMqUBxa/bu4+/NAyHEpDtZJzlJw==", "peer": true, "engines": { "node": ">=14.18.0" @@ -10611,7 +11351,8 @@ }, "node_modules/array-uniq": { "version": "1.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "engines": { "node": ">=0.10.0" } @@ -10625,8 +11366,9 @@ }, "node_modules/array.prototype.flat": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -10642,8 +11384,9 @@ }, "node_modules/array.prototype.flatmap": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -10659,7 +11402,8 @@ }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -10687,7 +11431,8 @@ }, "node_modules/asap": { "version": "2.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "peer": true }, "node_modules/asn1": { @@ -10770,14 +11515,16 @@ }, "node_modules/async-retry": { "version": "1.3.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", "dependencies": { "retry": "0.13.1" } }, "node_modules/async-retry/node_modules/retry": { "version": "0.13.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "engines": { "node": ">= 4" } @@ -10788,7 +11535,8 @@ }, "node_modules/at-least-node": { "version": "1.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "peer": true, "engines": { "node": ">= 4.0.0" @@ -10806,14 +11554,16 @@ }, "node_modules/atomic-sleep": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", "engines": { "node": ">=8.0.0" } }, "node_modules/available-typed-arrays": { "version": "1.0.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -10826,7 +11576,8 @@ }, "node_modules/aws-sdk": { "version": "2.1308.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1308.0.tgz", + "integrity": "sha512-tm4UXah8dCqt1geyxrtoyp6dN5QhuLjNeACUZEsffww5oZPMx24EX9dAtvtSu3UfIHwmbR74QomYi1c1u8Jndg==", "peer": true, "dependencies": { "buffer": "4.9.2", @@ -10846,7 +11597,8 @@ }, "node_modules/aws-sdk/node_modules/events": { "version": "1.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", "peer": true, "engines": { "node": ">=0.4.x" @@ -10854,17 +11606,20 @@ }, "node_modules/aws-sdk/node_modules/ieee754": { "version": "1.1.13", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "peer": true }, "node_modules/aws-sdk/node_modules/punycode": { "version": "1.3.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", "peer": true }, "node_modules/aws-sdk/node_modules/url": { "version": "0.10.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", "peer": true, "dependencies": { "punycode": "1.3.2", @@ -10873,7 +11628,8 @@ }, "node_modules/aws-sdk/node_modules/util": { "version": "0.12.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "peer": true, "dependencies": { "inherits": "^2.0.3", @@ -10885,7 +11641,8 @@ }, "node_modules/aws-sdk/node_modules/uuid": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", "peer": true, "bin": { "uuid": "dist/bin/uuid" @@ -10904,14 +11661,16 @@ }, "node_modules/axe-core": { "version": "4.4.2", - "license": "MPL-2.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.2.tgz", + "integrity": "sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA==", "engines": { "node": ">=12" } }, "node_modules/axios": { "version": "0.21.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", "peer": true, "dependencies": { "follow-redirects": "^1.14.0" @@ -11142,11 +11901,13 @@ }, "node_modules/before-after-hook": { "version": "2.2.3", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, "node_modules/bfj": { "version": "7.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", + "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", "dependencies": { "bluebird": "^3.5.5", "check-types": "^11.1.1", @@ -11224,11 +11985,13 @@ }, "node_modules/bowser": { "version": "2.11.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, "node_modules/boxen": { "version": "5.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", "peer": true, "dependencies": { "ansi-align": "^3.0.0", @@ -11424,7 +12187,8 @@ }, "node_modules/buffer-alloc": { "version": "1.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", "peer": true, "dependencies": { "buffer-alloc-unsafe": "^1.1.0", @@ -11433,7 +12197,8 @@ }, "node_modules/buffer-alloc-unsafe": { "version": "1.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", "peer": true }, "node_modules/buffer-crc32": { @@ -11445,7 +12210,8 @@ }, "node_modules/buffer-fill": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", "peer": true }, "node_modules/buffer-from": { @@ -11458,7 +12224,8 @@ }, "node_modules/builtin-modules": { "version": "3.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "peer": true, "engines": { "node": ">=6" @@ -11477,8 +12244,9 @@ }, "node_modules/bundle-require": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.3.tgz", + "integrity": "sha512-2iscZ3fcthP2vka4Y7j277YJevwmsby/FpFDwjgw34Nl7dtCpt7zz/4TexmHMzY6KZEih7En9ImlbbgUNNQGtA==", "dev": true, - "license": "MIT", "dependencies": { "load-tsconfig": "^0.2.3" }, @@ -11491,7 +12259,8 @@ }, "node_modules/cacache": { "version": "15.3.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -11518,7 +12287,8 @@ }, "node_modules/cacache/node_modules/lru-cache": { "version": "6.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { "yallist": "^4.0.0" }, @@ -11528,7 +12298,8 @@ }, "node_modules/cacache/node_modules/tar": { "version": "6.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -11543,14 +12314,16 @@ }, "node_modules/cacache/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "engines": { "node": ">=8" } }, "node_modules/cacache/node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/cache-base": { "version": "1.0.1", @@ -11572,7 +12345,8 @@ }, "node_modules/cacheable-lookup": { "version": "5.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", "peer": true, "engines": { "node": ">=10.6.0" @@ -11619,7 +12393,8 @@ }, "node_modules/cachedir": { "version": "2.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", + "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", "peer": true, "engines": { "node": ">=6" @@ -11627,7 +12402,8 @@ }, "node_modules/call-bind": { "version": "1.0.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -11728,8 +12504,7 @@ }, "node_modules/char-regex": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", "engines": { "node": ">=10" } @@ -11760,11 +12535,13 @@ }, "node_modules/check-types": { "version": "11.1.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz", + "integrity": "sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ==" }, "node_modules/cheerio": { "version": "1.0.0-rc.12", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", @@ -11783,7 +12560,8 @@ }, "node_modules/cheerio-select": { "version": "2.1.0", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", @@ -11798,7 +12576,8 @@ }, "node_modules/cheerio/node_modules/parse5": { "version": "7.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", "dependencies": { "entities": "^4.3.0" }, @@ -11808,7 +12587,8 @@ }, "node_modules/child-process-ext": { "version": "2.1.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/child-process-ext/-/child-process-ext-2.1.1.tgz", + "integrity": "sha512-0UQ55f51JBkOFa+fvR76ywRzxiPwQS3Xe8oe5bZRphpv+dIMeerW5Zn5e4cUy4COJwVtJyU0R79RMnw+aCqmGA==", "peer": true, "dependencies": { "cross-spawn": "^6.0.5", @@ -11820,7 +12600,8 @@ }, "node_modules/child-process-ext/node_modules/cross-spawn": { "version": "6.0.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "peer": true, "dependencies": { "nice-try": "^1.0.4", @@ -11835,7 +12616,8 @@ }, "node_modules/child-process-ext/node_modules/path-key": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "peer": true, "engines": { "node": ">=4" @@ -11843,7 +12625,8 @@ }, "node_modules/child-process-ext/node_modules/semver": { "version": "5.7.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "peer": true, "bin": { "semver": "bin/semver" @@ -11901,9 +12684,8 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + "version": "1.2.2", + "license": "MIT" }, "node_modules/class-utils": { "version": "0.3.6", @@ -11937,7 +12719,8 @@ }, "node_modules/cli-color": { "version": "2.0.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", + "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", "peer": true, "dependencies": { "d": "^1.0.1", @@ -11962,7 +12745,8 @@ }, "node_modules/cli-highlight": { "version": "2.1.11", - "license": "ISC", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", @@ -11981,22 +12765,26 @@ }, "node_modules/cli-highlight/node_modules/parse5": { "version": "5.1.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" }, "node_modules/cli-highlight/node_modules/parse5-htmlparser2-tree-adapter": { "version": "6.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "dependencies": { "parse5": "^6.0.1" } }, "node_modules/cli-highlight/node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { "version": "6.0.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, "node_modules/cli-highlight/node_modules/yargs": { "version": "16.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -12012,7 +12800,8 @@ }, "node_modules/cli-progress-footer": { "version": "2.3.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/cli-progress-footer/-/cli-progress-footer-2.3.2.tgz", + "integrity": "sha512-uzHGgkKdeA9Kr57eyH1W5HGiNShP8fV1ETq04HDNM1Un6ShXbHhwi/H8LNV9L1fQXKjEw0q5FUkEVNuZ+yZdSw==", "peer": true, "dependencies": { "cli-color": "^2.0.2", @@ -12039,7 +12828,8 @@ }, "node_modules/cli-sprintf-format": { "version": "1.1.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/cli-sprintf-format/-/cli-sprintf-format-1.1.1.tgz", + "integrity": "sha512-BbEjY9BEdA6wagVwTqPvmAwGB24U93rQPBFZUT8lNCDxXzre5LFHQUTJc70czjgUomVg8u8R5kW8oY9DYRFNeg==", "peer": true, "dependencies": { "cli-color": "^2.0.1", @@ -12053,7 +12843,8 @@ }, "node_modules/cli-sprintf-format/node_modules/has-flag": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "peer": true, "engines": { "node": ">=4" @@ -12061,7 +12852,8 @@ }, "node_modules/cli-sprintf-format/node_modules/supports-color": { "version": "6.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "peer": true, "dependencies": { "has-flag": "^3.0.0" @@ -12102,7 +12894,8 @@ }, "node_modules/clone": { "version": "1.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "peer": true, "engines": { "node": ">=0.8" @@ -12140,8 +12933,7 @@ }, "node_modules/co": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "license": "MIT", "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -12157,8 +12949,9 @@ }, "node_modules/code-suggester": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/code-suggester/-/code-suggester-4.1.1.tgz", + "integrity": "sha512-AGO1o4Bl4JlSeVCiFL9IpfH0MJyhtaMAwbO7qM+t/cNSz6URTPUZN+0fTtnAWfyeO5GbcGC9e18ArDbjkgpruA==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@octokit/rest": "^19.0.5", "@types/yargs": "^16.0.0", @@ -12177,8 +12970,9 @@ }, "node_modules/code-suggester/node_modules/yargs": { "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -12193,9 +12987,8 @@ } }, "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + "version": "1.0.1", + "license": "MIT" }, "node_modules/collection-visit": { "version": "1.0.0", @@ -12429,7 +13222,8 @@ }, "node_modules/content-disposition": { "version": "0.5.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "peer": true, "dependencies": { "safe-buffer": "5.2.1" @@ -12440,6 +13234,8 @@ }, "node_modules/content-disposition/node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -12454,7 +13250,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "peer": true }, "node_modules/conventional-changelog-angular": { @@ -12550,7 +13345,8 @@ }, "node_modules/cookiejar": { "version": "2.1.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" }, "node_modules/copy-concurrently": { "version": "1.0.5", @@ -12622,7 +13418,8 @@ }, "node_modules/cosmiconfig": { "version": "7.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -12711,7 +13508,8 @@ }, "node_modules/crc-32": { "version": "1.2.2", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "peer": true, "bin": { "crc32": "bin/crc32.njs" @@ -12821,7 +13619,7 @@ "node": ">=12" } }, - "node_modules/create-jest/node_modules/@jridgewell/trace-mapping": { + "node_modules/create-jest/node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", @@ -12949,9 +13747,9 @@ } }, "node_modules/create-jest/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/create-jest/node_modules/ts-node": { "version": "10.9.2", @@ -13004,7 +13802,8 @@ }, "node_modules/cron-parser": { "version": "4.7.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.7.1.tgz", + "integrity": "sha512-WguFaoQ0hQ61SgsCZLHUcNbAvlK0lypKXu62ARguefYmjzaOXIVRNrAmyXzabTwUn4sQvQLkk6bjH+ipGfw8bA==", "peer": true, "dependencies": { "luxon": "^3.2.1" @@ -13015,14 +13814,16 @@ }, "node_modules/cross-fetch": { "version": "3.1.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", "dependencies": { "node-fetch": "2.6.7" } }, "node_modules/cross-fetch/node_modules/node-fetch": { "version": "2.6.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -13040,15 +13841,18 @@ }, "node_modules/cross-fetch/node_modules/tr46": { "version": "0.0.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/cross-fetch/node_modules/webidl-conversions": { "version": "3.0.1", - "license": "BSD-2-Clause" + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/cross-fetch/node_modules/whatwg-url": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -13094,7 +13898,8 @@ }, "node_modules/css-select": { "version": "5.1.0", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", @@ -13138,7 +13943,8 @@ }, "node_modules/d": { "version": "1.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "peer": true, "dependencies": { "es5-ext": "^0.10.50", @@ -13147,7 +13953,8 @@ }, "node_modules/d/node_modules/type": { "version": "1.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", "peer": true }, "node_modules/daemonize2": { @@ -13180,7 +13987,8 @@ }, "node_modules/data-view-buffer": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -13195,7 +14003,8 @@ }, "node_modules/data-view-byte-length": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -13210,7 +14019,8 @@ }, "node_modules/data-view-byte-offset": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -13233,7 +14043,8 @@ }, "node_modules/dayjs": { "version": "1.11.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==", "peer": true }, "node_modules/debug": { @@ -13281,14 +14092,16 @@ }, "node_modules/decode-uri-component": { "version": "0.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "engines": { "node": ">=0.10" } }, "node_modules/decompress": { "version": "4.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", "peer": true, "dependencies": { "decompress-tar": "^4.0.0", @@ -13317,7 +14130,8 @@ }, "node_modules/decompress-tar": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", "peer": true, "dependencies": { "file-type": "^5.2.0", @@ -13330,7 +14144,8 @@ }, "node_modules/decompress-tar/node_modules/bl": { "version": "1.2.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", "peer": true, "dependencies": { "readable-stream": "^2.3.5", @@ -13339,7 +14154,8 @@ }, "node_modules/decompress-tar/node_modules/file-type": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", "peer": true, "engines": { "node": ">=4" @@ -13347,7 +14163,8 @@ }, "node_modules/decompress-tar/node_modules/is-stream": { "version": "1.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "peer": true, "engines": { "node": ">=0.10.0" @@ -13355,7 +14172,8 @@ }, "node_modules/decompress-tar/node_modules/readable-stream": { "version": "2.3.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -13369,7 +14187,8 @@ }, "node_modules/decompress-tar/node_modules/string_decoder": { "version": "1.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -13377,7 +14196,8 @@ }, "node_modules/decompress-tar/node_modules/tar-stream": { "version": "1.6.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "peer": true, "dependencies": { "bl": "^1.0.0", @@ -13394,7 +14214,8 @@ }, "node_modules/decompress-tarbz2": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", "peer": true, "dependencies": { "decompress-tar": "^4.1.0", @@ -13409,7 +14230,8 @@ }, "node_modules/decompress-tarbz2/node_modules/file-type": { "version": "6.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", "peer": true, "engines": { "node": ">=4" @@ -13417,7 +14239,8 @@ }, "node_modules/decompress-tarbz2/node_modules/is-stream": { "version": "1.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "peer": true, "engines": { "node": ">=0.10.0" @@ -13425,7 +14248,8 @@ }, "node_modules/decompress-targz": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", "peer": true, "dependencies": { "decompress-tar": "^4.1.1", @@ -13438,7 +14262,8 @@ }, "node_modules/decompress-targz/node_modules/file-type": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", "peer": true, "engines": { "node": ">=4" @@ -13446,7 +14271,8 @@ }, "node_modules/decompress-targz/node_modules/is-stream": { "version": "1.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "peer": true, "engines": { "node": ">=0.10.0" @@ -13454,7 +14280,8 @@ }, "node_modules/decompress-unzip": { "version": "4.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", "peer": true, "dependencies": { "file-type": "^3.8.0", @@ -13468,7 +14295,8 @@ }, "node_modules/decompress-unzip/node_modules/file-type": { "version": "3.9.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", "peer": true, "engines": { "node": ">=0.10.0" @@ -13476,7 +14304,8 @@ }, "node_modules/decompress-unzip/node_modules/get-stream": { "version": "2.3.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", "peer": true, "dependencies": { "object-assign": "^4.0.1", @@ -13488,7 +14317,8 @@ }, "node_modules/decompress-unzip/node_modules/pify": { "version": "2.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "peer": true, "engines": { "node": ">=0.10.0" @@ -13496,7 +14326,8 @@ }, "node_modules/decompress/node_modules/make-dir": { "version": "1.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "peer": true, "dependencies": { "pify": "^3.0.0" @@ -13507,7 +14338,8 @@ }, "node_modules/decompress/node_modules/make-dir/node_modules/pify": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "peer": true, "engines": { "node": ">=4" @@ -13515,7 +14347,8 @@ }, "node_modules/decompress/node_modules/pify": { "version": "2.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "peer": true, "engines": { "node": ">=0.10.0" @@ -13557,7 +14390,8 @@ }, "node_modules/defaults": { "version": "1.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "peer": true, "dependencies": { "clone": "^1.0.2" @@ -13573,7 +14407,8 @@ }, "node_modules/deferred": { "version": "0.7.11", - "license": "ISC", + "resolved": "https://registry.npmjs.org/deferred/-/deferred-0.7.11.tgz", + "integrity": "sha512-8eluCl/Blx4YOGwMapBvXRKxHXhA8ejDXYzEaK8+/gtcm8hRMhSLmXSqDmNUKNc/C8HNSmuyyp/hflhqDAvK2A==", "peer": true, "dependencies": { "d": "^1.0.1", @@ -13585,7 +14420,8 @@ }, "node_modules/define-data-property": { "version": "1.1.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -13600,7 +14436,8 @@ }, "node_modules/define-lazy-prop": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "peer": true, "engines": { "node": ">=8" @@ -13608,7 +14445,8 @@ }, "node_modules/define-properties": { "version": "1.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -13667,7 +14505,8 @@ }, "node_modules/desm": { "version": "1.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/desm/-/desm-1.3.0.tgz", + "integrity": "sha512-RvlHN2gfYA0BpCfjpWzCdQeR6p5U+84f5DzcirLow86UA/OcpwuOqXRC4Oz0bG9rzcJPVtMT6ZgNtjp4qh+uqA==", "peer": true }, "node_modules/detect-indent": { @@ -13688,11 +14527,13 @@ }, "node_modules/devtools-protocol": { "version": "0.0.869402", - "license": "BSD-3-Clause" + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.869402.tgz", + "integrity": "sha512-VvlVYY+VDJe639yHs5PHISzdWTLL3Aw8rO4cvUtwvoxFd6FHbE4OpHHcde52M6096uYYazAmd4l0o5VuFRO2WA==" }, "node_modules/dezalgo": { "version": "1.0.4", - "license": "ISC", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", "peer": true, "dependencies": { "asap": "^2.0.0", @@ -13754,7 +14595,8 @@ }, "node_modules/dom-serializer": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -13784,7 +14626,8 @@ }, "node_modules/domhandler": { "version": "5.0.3", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dependencies": { "domelementtype": "^2.3.0" }, @@ -13797,7 +14640,8 @@ }, "node_modules/domutils": { "version": "3.0.1", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -13823,7 +14667,8 @@ }, "node_modules/dotenv": { "version": "16.0.3", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "peer": true, "engines": { "node": ">=12" @@ -13831,7 +14676,8 @@ }, "node_modules/dotenv-expand": { "version": "9.0.0", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-9.0.0.tgz", + "integrity": "sha512-uW8Hrhp5ammm9x7kBLR6jDfujgaDarNA02tprvZdyrJ7MpdzD1KyrIHG4l+YoC2fJ2UcdFdNWNWIjt+sexBHJw==", "peer": true, "engines": { "node": ">=12" @@ -13879,7 +14725,8 @@ }, "node_modules/duration": { "version": "0.2.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", + "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", "peer": true, "dependencies": { "d": "1", @@ -13888,7 +14735,8 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "peer": true }, "node_modules/ecc-jsbn": { @@ -13904,9 +14752,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.749", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.749.tgz", - "integrity": "sha512-LRMMrM9ITOvue0PoBrvNIraVmuDbJV5QC9ierz/z5VilMdPOVMjOtpICNld3PuXuTZ3CHH/UPxX9gHhAPwi+0Q==" + "version": "1.4.747", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.747.tgz", + "integrity": "sha512-+FnSWZIAvFHbsNVmUxhEqWiaOiPMcfum1GQzlWCg/wLigVtshOsjXHyEFfmt6cFK6+HkS3QOJBv6/3OPumbBfw==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -13974,7 +14822,8 @@ }, "node_modules/endent": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", "dependencies": { "dedent": "^0.7.0", "fast-json-parse": "^1.0.3", @@ -14035,7 +14884,8 @@ }, "node_modules/entities": { "version": "4.4.0", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", "engines": { "node": ">=0.12" }, @@ -14083,7 +14933,8 @@ }, "node_modules/es-abstract": { "version": "1.23.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -14141,7 +14992,8 @@ }, "node_modules/es-define-property": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -14151,14 +15003,16 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "engines": { "node": ">= 0.4" } }, "node_modules/es-object-atoms": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dependencies": { "es-errors": "^1.3.0" }, @@ -14168,7 +15022,8 @@ }, "node_modules/es-set-tostringtag": { "version": "2.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -14180,8 +15035,9 @@ }, "node_modules/es-shim-unscopables": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", "dev": true, - "license": "MIT", "dependencies": { "has": "^1.0.3" } @@ -14203,8 +15059,9 @@ }, "node_modules/es5-ext": { "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", "hasInstallScript": true, - "license": "ISC", "peer": true, "dependencies": { "es6-iterator": "^2.0.3", @@ -14217,7 +15074,8 @@ }, "node_modules/es6-iterator": { "version": "2.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "peer": true, "dependencies": { "d": "1", @@ -14231,7 +15089,8 @@ }, "node_modules/es6-set": { "version": "0.1.6", - "license": "ISC", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.6.tgz", + "integrity": "sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==", "peer": true, "dependencies": { "d": "^1.0.1", @@ -14247,7 +15106,8 @@ }, "node_modules/es6-symbol": { "version": "3.1.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "peer": true, "dependencies": { "d": "^1.0.1", @@ -14256,7 +15116,8 @@ }, "node_modules/es6-weak-map": { "version": "2.0.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "peer": true, "dependencies": { "d": "1", @@ -14267,9 +15128,10 @@ }, "node_modules/esbuild": { "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", "dev": true, "hasInstallScript": true, - "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -14333,8 +15195,9 @@ }, "node_modules/eslint": { "version": "8.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", + "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", @@ -14389,8 +15252,9 @@ }, "node_modules/eslint-config-prettier": { "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", "dev": true, - "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -14400,8 +15264,9 @@ }, "node_modules/eslint-import-resolver-node": { "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.11.0", @@ -14410,16 +15275,18 @@ }, "node_modules/eslint-import-resolver-node/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-module-utils": { "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -14434,16 +15301,18 @@ }, "node_modules/eslint-module-utils/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import": { "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", "dev": true, - "license": "MIT", "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -14470,8 +15339,9 @@ }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -14489,8 +15359,9 @@ }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver.js" } @@ -14505,8 +15376,9 @@ }, "node_modules/eslint-scope": { "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -14555,8 +15427,9 @@ }, "node_modules/eslint/node_modules/eslint-scope": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -14567,8 +15440,9 @@ }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -14578,16 +15452,18 @@ }, "node_modules/eslint/node_modules/estraverse": { "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -14630,7 +15506,8 @@ }, "node_modules/esniff": { "version": "1.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-1.1.0.tgz", + "integrity": "sha512-vmHXOeOt7FJLsqofvFk4WB3ejvcHizCd8toXXwADmYfd02p2QwHRgkUbhYDX54y08nqk818CUTWipgZGlyN07g==", "peer": true, "dependencies": { "d": "1", @@ -14639,8 +15516,9 @@ }, "node_modules/espree": { "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", @@ -14655,8 +15533,9 @@ }, "node_modules/espree/node_modules/eslint-visitor-keys": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "dev": true, - "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -14677,8 +15556,9 @@ }, "node_modules/esquery": { "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -14713,7 +15593,8 @@ }, "node_modules/essentials": { "version": "1.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/essentials/-/essentials-1.2.0.tgz", + "integrity": "sha512-kP/j7Iw7KeNE8b/o7+tr9uX2s1wegElGOoGZ2Xm35qBr4BbbEcH3/bxR2nfH9l9JANCq9AUrvKw+gRuHtZp0HQ==", "peer": true, "dependencies": { "uni-global": "^1.0.0" @@ -14736,7 +15617,8 @@ }, "node_modules/event-emitter": { "version": "0.3.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "peer": true, "dependencies": { "d": "1", @@ -14745,7 +15627,8 @@ }, "node_modules/event-target-shim": { "version": "5.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "engines": { "node": ">=6" } @@ -14897,7 +15780,8 @@ }, "node_modules/ext": { "version": "1.7.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "peer": true, "dependencies": { "type": "^2.7.2" @@ -14905,7 +15789,8 @@ }, "node_modules/ext-list": { "version": "2.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", "peer": true, "dependencies": { "mime-db": "^1.28.0" @@ -14916,7 +15801,8 @@ }, "node_modules/ext-name": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", "peer": true, "dependencies": { "ext-list": "^2.0.0", @@ -15023,7 +15909,8 @@ }, "node_modules/extract-zip": { "version": "2.0.1", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -15041,7 +15928,8 @@ }, "node_modules/extract-zip/node_modules/get-stream": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dependencies": { "pump": "^3.0.0" }, @@ -15067,7 +15955,8 @@ }, "node_modules/fast-copy": { "version": "3.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", + "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==", "peer": true }, "node_modules/fast-deep-equal": { @@ -15090,7 +15979,8 @@ }, "node_modules/fast-json-parse": { "version": "1.0.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", @@ -15103,7 +15993,8 @@ }, "node_modules/fast-redact": { "version": "3.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", + "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", "engines": { "node": ">=6" } @@ -15114,7 +16005,8 @@ }, "node_modules/fast-xml-parser": { "version": "4.0.11", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz", + "integrity": "sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA==", "dependencies": { "strnum": "^1.0.5" }, @@ -15128,7 +16020,8 @@ }, "node_modules/fastest-levenshtein": { "version": "1.0.16", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "engines": { "node": ">= 4.9.1" } @@ -15160,6 +16053,8 @@ }, "node_modules/fetch-blob": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "funding": [ { "type": "github", @@ -15170,7 +16065,6 @@ "url": "https://paypal.me/jimmywarting" } ], - "license": "MIT", "peer": true, "dependencies": { "node-domexception": "^1.0.0", @@ -15217,7 +16111,8 @@ }, "node_modules/file-type": { "version": "16.5.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", "peer": true, "dependencies": { "readable-web-to-node-stream": "^3.0.0", @@ -15238,14 +16133,16 @@ }, "node_modules/file-url": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", + "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", "engines": { "node": ">=8" } }, "node_modules/filename-reserved-regex": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", "peer": true, "engines": { "node": ">=4" @@ -15253,7 +16150,8 @@ }, "node_modules/filenamify": { "version": "4.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "peer": true, "dependencies": { "filename-reserved-regex": "^2.0.0", @@ -15269,7 +16167,8 @@ }, "node_modules/filesize": { "version": "10.0.6", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.0.6.tgz", + "integrity": "sha512-rzpOZ4C9vMFDqOa6dNpog92CoLYjD79dnjLk2TYDDtImRIyLTOzqojCb05Opd1WuiWjs+fshhCgTd8cl7y5t+g==", "peer": true, "engines": { "node": ">= 10.4.0" @@ -15405,7 +16304,8 @@ }, "node_modules/find-requires": { "version": "1.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/find-requires/-/find-requires-1.0.0.tgz", + "integrity": "sha512-UME7hNwBfzeISSFQcBEDemEEskpOjI/shPrpJM5PI4DSdn6hX0dmz+2dL70blZER2z8tSnTRL+2rfzlYgtbBoQ==", "peer": true, "dependencies": { "es5-ext": "^0.10.49", @@ -15519,7 +16419,8 @@ }, "node_modules/for-each": { "version": "0.3.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dependencies": { "is-callable": "^1.1.3" } @@ -15552,7 +16453,8 @@ }, "node_modules/formdata-polyfill": { "version": "4.0.10", - "license": "MIT", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "peer": true, "dependencies": { "fetch-blob": "^3.1.2" @@ -15672,7 +16574,8 @@ }, "node_modules/fs2": { "version": "0.3.9", - "license": "ISC", + "resolved": "https://registry.npmjs.org/fs2/-/fs2-0.3.9.tgz", + "integrity": "sha512-WsOqncODWRlkjwll+73bAxVW3JPChDgaPX3DT4iTTm73UmG4VgALa7LaFblP232/DN60itkOrPZ8kaP1feksGQ==", "peer": true, "dependencies": { "d": "^1.0.1", @@ -15700,14 +16603,16 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/function.prototype.name": { "version": "1.1.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -15728,7 +16633,8 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -15774,7 +16680,8 @@ }, "node_modules/get-intrinsic": { "version": "1.2.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -15829,7 +16736,8 @@ }, "node_modules/get-stdin": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "peer": true, "engines": { "node": ">=10" @@ -15850,7 +16758,8 @@ }, "node_modules/get-symbol-description": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -15936,8 +16845,9 @@ }, "node_modules/globals": { "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -15950,7 +16860,8 @@ }, "node_modules/globalthis": { "version": "1.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dependencies": { "define-properties": "^1.1.3" }, @@ -15981,7 +16892,8 @@ }, "node_modules/gopd": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -16031,7 +16943,8 @@ }, "node_modules/graphlib": { "version": "2.1.8", - "license": "MIT", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", "peer": true, "dependencies": { "lodash": "^4.17.15" @@ -16117,7 +17030,8 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { "es-define-property": "^1.0.0" }, @@ -16127,7 +17041,8 @@ }, "node_modules/has-proto": { "version": "1.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -16147,7 +17062,8 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dependencies": { "has-symbols": "^1.0.3" }, @@ -16263,7 +17179,8 @@ }, "node_modules/hasown": { "version": "2.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -16280,7 +17197,8 @@ }, "node_modules/help-me": { "version": "4.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", + "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", "peer": true, "dependencies": { "glob": "^8.0.0", @@ -16289,7 +17207,8 @@ }, "node_modules/help-me/node_modules/brace-expansion": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "peer": true, "dependencies": { "balanced-match": "^1.0.0" @@ -16297,7 +17216,8 @@ }, "node_modules/help-me/node_modules/glob": { "version": "8.1.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "peer": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -16315,7 +17235,8 @@ }, "node_modules/help-me/node_modules/minimatch": { "version": "5.1.6", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "peer": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -16337,7 +17258,8 @@ }, "node_modules/hexoid": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", "peer": true, "engines": { "node": ">=8" @@ -16345,7 +17267,8 @@ }, "node_modules/highlight.js": { "version": "10.7.3", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", "engines": { "node": "*" } @@ -16361,6 +17284,8 @@ }, "node_modules/hogan.js": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", + "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", "dependencies": { "mkdirp": "0.3.0", "nopt": "1.0.10" @@ -16371,19 +17296,25 @@ }, "node_modules/hogan.js/node_modules/mkdirp": { "version": "0.3.0", - "license": "MIT/X11", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", "engines": { "node": "*" } }, "node_modules/hogan.js/node_modules/nopt": { "version": "1.0.10", - "license": "MIT", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" } }, "node_modules/hook-std": { @@ -16395,7 +17326,8 @@ }, "node_modules/hoopy": { "version": "0.1.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", "engines": { "node": ">= 6.0.0" } @@ -16426,7 +17358,8 @@ }, "node_modules/html_codesniffer": { "version": "2.5.1", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/html_codesniffer/-/html_codesniffer-2.5.1.tgz", + "integrity": "sha512-vcz0yAaX/OaV6sdNHuT9alBOKkSxYb8h5Yq26dUqgi7XmCgGUSa7U9PiY1PBXQFMjKv1wVPs5/QzHlGuxPDUGg==", "engines": { "node": ">=6" } @@ -16438,6 +17371,8 @@ }, "node_modules/htmlparser2": { "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -16445,7 +17380,6 @@ "url": "https://github.com/sponsors/fb55" } ], - "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -16455,7 +17389,22 @@ }, "node_modules/http-cache-semantics": { "version": "4.1.1", - "license": "BSD-2-Clause" + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http-errors": { + "version": "1.8.1", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } }, "node_modules/http-proxy": { "version": "1.18.1", @@ -16496,7 +17445,8 @@ }, "node_modules/http2-wrapper": { "version": "1.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", "peer": true, "dependencies": { "quick-lru": "^5.1.1", @@ -16508,7 +17458,8 @@ }, "node_modules/http2-wrapper/node_modules/quick-lru": { "version": "5.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "peer": true, "engines": { "node": ">=10" @@ -16653,12 +17604,14 @@ }, "node_modules/immediate": { "version": "3.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "peer": true }, "node_modules/import-cwd": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", + "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", "dependencies": { "import-from": "^3.0.0" }, @@ -16668,7 +17621,8 @@ }, "node_modules/import-cwd/node_modules/import-from": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", + "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", "dependencies": { "resolve-from": "^5.0.0" }, @@ -16844,7 +17798,8 @@ }, "node_modules/internal-slot": { "version": "1.0.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -16878,7 +17833,8 @@ }, "node_modules/is": { "version": "3.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", + "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", "engines": { "node": "*" } @@ -16920,7 +17876,8 @@ }, "node_modules/is-array-buffer": { "version": "3.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -16976,7 +17933,8 @@ }, "node_modules/is-callable": { "version": "1.2.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { "node": ">= 0.4" }, @@ -16997,7 +17955,8 @@ }, "node_modules/is-core-module": { "version": "2.11.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dependencies": { "has": "^1.0.3" }, @@ -17027,7 +17986,8 @@ }, "node_modules/is-data-view": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dependencies": { "is-typed-array": "^1.1.13" }, @@ -17072,7 +18032,8 @@ }, "node_modules/is-docker": { "version": "2.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "peer": true, "bin": { "is-docker": "cli.js" @@ -17107,15 +18068,15 @@ }, "node_modules/is-generator-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/is-generator-function": { "version": "1.0.10", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "peer": true, "dependencies": { "has-tostringtag": "^1.0.0" @@ -17176,7 +18137,8 @@ }, "node_modules/is-interactive": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "peer": true, "engines": { "node": ">=8" @@ -17188,12 +18150,14 @@ }, "node_modules/is-natural-number": { "version": "4.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==", "peer": true }, "node_modules/is-negative-zero": { "version": "2.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "engines": { "node": ">= 0.4" }, @@ -17262,12 +18226,14 @@ }, "node_modules/is-promise": { "version": "2.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", "peer": true }, "node_modules/is-regex": { "version": "1.1.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -17295,7 +18261,8 @@ }, "node_modules/is-shared-array-buffer": { "version": "1.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dependencies": { "call-bind": "^1.0.7" }, @@ -17355,7 +18322,8 @@ }, "node_modules/is-typed-array": { "version": "1.1.13", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dependencies": { "which-typed-array": "^1.1.14" }, @@ -17465,7 +18433,8 @@ }, "node_modules/isomorphic-ws": { "version": "4.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", "peer": true, "peerDependencies": { "ws": "*" @@ -17587,7 +18556,8 @@ }, "node_modules/java-invoke-local": { "version": "0.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/java-invoke-local/-/java-invoke-local-0.0.6.tgz", + "integrity": "sha512-gZmQKe1QrfkkMjCn8Qv9cpyJFyogTYqkP5WCobX5RNaHsJzIV/6NvAnlnouOcwKr29QrxLGDGcqYuJ+ae98s1A==", "peer": true, "bin": { "java-invoke-local": "lib/cli.js" @@ -17882,9 +18852,9 @@ } }, "node_modules/jest-circus/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-cli": { "version": "29.7.0", @@ -18059,9 +19029,9 @@ } }, "node_modules/jest-cli/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-cli/node_modules/ts-node": { "version": "10.9.2", @@ -18210,9 +19180,9 @@ } }, "node_modules/jest-each/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-environment-node": { "version": "29.7.0", @@ -18363,9 +19333,9 @@ } }, "node_modules/jest-environment-node/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-get-type": { "version": "27.5.1", @@ -18474,9 +19444,9 @@ } }, "node_modules/jest-leak-detector/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-matcher-utils": { "version": "27.5.1", @@ -18556,9 +19526,8 @@ } }, "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "version": "1.2.2", + "license": "MIT", "engines": { "node": ">=6" }, @@ -18804,9 +19773,9 @@ } }, "node_modules/jest-runner/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-runner/node_modules/source-map-support": { "version": "0.5.13", @@ -18996,9 +19965,9 @@ } }, "node_modules/jest-runtime/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-snapshot": { "version": "29.7.0", @@ -19174,9 +20143,9 @@ } }, "node_modules/jest-snapshot/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-snapshot/node_modules/semver": { "version": "7.6.0", @@ -19294,9 +20263,9 @@ } }, "node_modules/jest-validate/node_modules/react-is": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.0.tgz", - "integrity": "sha512-wRiUsea88TjKDc4FBEn+sLvIDesp6brMbGWnJGjew2waAc9evdhja/2LvePc898HJbHw0L+MTWy7NhpnELAvLQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/jest-watcher": { "version": "29.7.0", @@ -19406,7 +20375,8 @@ }, "node_modules/jmespath": { "version": "0.16.0", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", "peer": true, "engines": { "node": ">= 0.6.0" @@ -19414,7 +20384,8 @@ }, "node_modules/jose": { "version": "4.11.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.11.2.tgz", + "integrity": "sha512-njj0VL2TsIxCtgzhO+9RRobBvws4oYyCM8TpvoUQwl/MbIM3NFJRR9+e6x0sS5xXaP1t6OCBkaBME98OV9zU5A==", "peer": true, "funding": { "url": "https://github.com/sponsors/panva" @@ -19422,7 +20393,8 @@ }, "node_modules/joycon": { "version": "3.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", "peer": true, "engines": { "node": ">=10" @@ -19430,12 +20402,14 @@ }, "node_modules/jpeg-js": { "version": "0.4.4", - "license": "BSD-3-Clause" + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" }, "node_modules/js-sdsl": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", + "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", "dev": true, - "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" @@ -19443,7 +20417,8 @@ }, "node_modules/js-string-escape": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", "peer": true, "engines": { "node": ">= 0.8" @@ -19484,7 +20459,8 @@ }, "node_modules/json-cycle": { "version": "1.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/json-cycle/-/json-cycle-1.3.0.tgz", + "integrity": "sha512-FD/SedD78LCdSvJaOUQAXseT8oQBb5z6IVYaQaCrVUlu9zOAr1BDdKyVYQaSD/GDsAMrXpKcOyBD4LIl8nfjHw==", "peer": true, "engines": { "node": ">= 4" @@ -19500,7 +20476,8 @@ }, "node_modules/json-refs": { "version": "3.0.15", - "license": "MIT", + "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-3.0.15.tgz", + "integrity": "sha512-0vOQd9eLNBL18EGl5yYaO44GhixmImes2wiYn9Z3sag3QnehWrYWlB9AFtMxCL2Bj3fyxgDYkxGFEU/chlYssw==", "peer": true, "dependencies": { "commander": "~4.1.1", @@ -19521,7 +20498,8 @@ }, "node_modules/json-refs/node_modules/argparse": { "version": "1.0.10", - "license": "MIT", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "peer": true, "dependencies": { "sprintf-js": "~1.0.2" @@ -19529,7 +20507,8 @@ }, "node_modules/json-refs/node_modules/commander": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "peer": true, "engines": { "node": ">= 6" @@ -19537,7 +20516,8 @@ }, "node_modules/json-refs/node_modules/js-yaml": { "version": "3.14.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -19566,7 +20546,8 @@ }, "node_modules/json5": { "version": "2.2.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "bin": { "json5": "lib/cli.js" }, @@ -19603,7 +20584,8 @@ }, "node_modules/jsonpath-plus": { "version": "7.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-7.2.0.tgz", + "integrity": "sha512-zBfiUPM5nD0YZSBT/o/fbCUlCcepMIdP0CJZxM1+KgA4f2T206f6VAg9e7mX35+KlMaIc5qXW34f3BnwJ3w+RA==", "peer": true, "engines": { "node": ">=12.0.0" @@ -19622,7 +20604,8 @@ }, "node_modules/jsonschema": { "version": "1.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", "peer": true, "engines": { "node": "*" @@ -19658,7 +20641,8 @@ }, "node_modules/jszip": { "version": "3.10.1", - "license": "(MIT OR GPL-3.0-or-later)", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "peer": true, "dependencies": { "lie": "~3.3.0", @@ -19669,7 +20653,8 @@ }, "node_modules/jszip/node_modules/readable-stream": { "version": "2.3.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "peer": true, "dependencies": { "core-util-is": "~1.0.0", @@ -19683,7 +20668,8 @@ }, "node_modules/jszip/node_modules/string_decoder": { "version": "1.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "peer": true, "dependencies": { "safe-buffer": "~5.1.0" @@ -19691,7 +20677,8 @@ }, "node_modules/jwt-decode": { "version": "2.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", + "integrity": "sha512-86GgN2vzfUu7m9Wcj63iUkuDzFNYFVmjeDm2GzWpUk+opB0pEpMsw6ePCMrhYkumz2C1ihqtZzOMAg7FiXcNoQ==", "peer": true }, "node_modules/keyv": { @@ -19781,8 +20768,7 @@ }, "node_modules/leven": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", "engines": { "node": ">=6" } @@ -19801,7 +20787,8 @@ }, "node_modules/libnpmpack": { "version": "3.1.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/libnpmpack/-/libnpmpack-3.1.0.tgz", + "integrity": "sha512-dO0ER8L6TPINOSyCAy/XTwsKIz42Bg+SB1XX9zCoaHimP7oqzV7O8PJGoPfEduLt8zidwu8oNW3nYrA43M6VCQ==", "dependencies": { "@npmcli/run-script": "^2.0.0", "npm-package-arg": "^8.1.0", @@ -19813,7 +20800,8 @@ }, "node_modules/libnpmpack/node_modules/@npmcli/git": { "version": "2.1.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", + "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", "dependencies": { "@npmcli/promise-spawn": "^1.3.2", "lru-cache": "^6.0.0", @@ -19827,7 +20815,8 @@ }, "node_modules/libnpmpack/node_modules/ignore-walk": { "version": "4.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", + "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", "dependencies": { "minimatch": "^3.0.4" }, @@ -19837,7 +20826,8 @@ }, "node_modules/libnpmpack/node_modules/lru-cache": { "version": "6.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { "yallist": "^4.0.0" }, @@ -19847,7 +20837,8 @@ }, "node_modules/libnpmpack/node_modules/npm-install-checks": { "version": "4.0.0", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", "dependencies": { "semver": "^7.1.1" }, @@ -19857,7 +20848,8 @@ }, "node_modules/libnpmpack/node_modules/npm-packlist": { "version": "3.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", + "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", "dependencies": { "glob": "^7.1.6", "ignore-walk": "^4.0.1", @@ -19873,7 +20865,8 @@ }, "node_modules/libnpmpack/node_modules/npm-pick-manifest": { "version": "6.1.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", + "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", "dependencies": { "npm-install-checks": "^4.0.0", "npm-normalize-package-bin": "^1.0.1", @@ -19883,7 +20876,8 @@ }, "node_modules/libnpmpack/node_modules/pacote": { "version": "12.0.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-12.0.3.tgz", + "integrity": "sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow==", "dependencies": { "@npmcli/git": "^2.1.0", "@npmcli/installed-package-contents": "^1.0.6", @@ -19914,7 +20908,8 @@ }, "node_modules/libnpmpack/node_modules/tar": { "version": "6.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -19929,14 +20924,16 @@ }, "node_modules/libnpmpack/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "engines": { "node": ">=8" } }, "node_modules/libnpmpack/node_modules/which": { "version": "2.0.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dependencies": { "isexe": "^2.0.0" }, @@ -19949,11 +20946,13 @@ }, "node_modules/libnpmpack/node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/libnpmpublish": { "version": "5.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/libnpmpublish/-/libnpmpublish-5.0.1.tgz", + "integrity": "sha512-S9HvvO8kGWWuGFvAQyw0T5NWxib21ktA1REGTB7I+GBqDjyYOjjwzJaavtTxDD8ID18dKCluOXg0PdMmRdKfHA==", "dependencies": { "normalize-package-data": "^3.0.2", "npm-package-arg": "^8.1.2", @@ -19967,7 +20966,8 @@ }, "node_modules/lie": { "version": "3.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "peer": true, "dependencies": { "immediate": "~3.0.5" @@ -20136,8 +21136,9 @@ }, "node_modules/load-tsconfig": { "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", "dev": true, - "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -20151,7 +21152,8 @@ }, "node_modules/loader-utils": { "version": "1.4.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -20163,7 +21165,8 @@ }, "node_modules/loader-utils/node_modules/json5": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dependencies": { "minimist": "^1.2.0" }, @@ -20241,7 +21244,8 @@ }, "node_modules/log": { "version": "6.3.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/log/-/log-6.3.1.tgz", + "integrity": "sha512-McG47rJEWOkXTDioZzQNydAVvZNeEkSyLJ1VWkFwfW+o1knW+QSi8D1KjPn/TnctV+q99lkvJNe1f0E1IjfY2A==", "peer": true, "dependencies": { "d": "^1.0.1", @@ -20255,7 +21259,8 @@ }, "node_modules/log-node": { "version": "8.0.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/log-node/-/log-node-8.0.3.tgz", + "integrity": "sha512-1UBwzgYiCIDFs8A0rM2QdBFo8Wd8UQ0HrSTu/MNI+/2zN3NoHRj2fhplurAyuxTYUXu3Oohugq1jAn5s05u1MQ==", "peer": true, "dependencies": { "ansi-regex": "^5.0.1", @@ -20276,7 +21281,8 @@ }, "node_modules/log-node/node_modules/supports-color": { "version": "8.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -20373,7 +21379,8 @@ }, "node_modules/long-timeout": { "version": "0.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", + "integrity": "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==", "peer": true }, "node_modules/loupe": { @@ -20403,7 +21410,8 @@ }, "node_modules/lru-queue": { "version": "0.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", "peer": true, "dependencies": { "es5-ext": "~0.10.2" @@ -20411,7 +21419,8 @@ }, "node_modules/luxon": { "version": "3.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.2.1.tgz", + "integrity": "sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg==", "peer": true, "engines": { "node": ">=12" @@ -20446,7 +21455,8 @@ }, "node_modules/make-fetch-happen": { "version": "9.1.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -20471,7 +21481,8 @@ }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "6.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { "yallist": "^4.0.0" }, @@ -20481,7 +21492,8 @@ }, "node_modules/make-fetch-happen/node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/makeerror": { "version": "1.0.12", @@ -20529,7 +21541,8 @@ }, "node_modules/memoizee": { "version": "0.4.15", - "license": "ISC", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", "peer": true, "dependencies": { "d": "^1.0.1", @@ -20761,7 +21774,8 @@ }, "node_modules/minipass-fetch": { "version": "1.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", "dependencies": { "minipass": "^3.1.0", "minipass-sized": "^1.0.3", @@ -20921,7 +21935,8 @@ }, "node_modules/mkdirp-classic": { "version": "0.5.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "node_modules/mocha": { "version": "8.4.0", @@ -21237,7 +22252,8 @@ }, "node_modules/mz": { "version": "2.7.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -21356,7 +22372,8 @@ }, "node_modules/native-promise-only": { "version": "0.8.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==", "peer": true }, "node_modules/natural-compare": { @@ -21365,12 +22382,14 @@ }, "node_modules/natural-compare-lite": { "version": "1.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true }, "node_modules/ncjsm": { "version": "4.3.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/ncjsm/-/ncjsm-4.3.2.tgz", + "integrity": "sha512-6d1VWA7FY31CpI4Ki97Fpm36jfURkVbpktizp8aoVViTZRQgr/0ddmlKerALSSlzfwQRBeSq1qwwVcBJK4Sk7Q==", "peer": true, "dependencies": { "builtin-modules": "^3.3.0", @@ -21412,12 +22431,14 @@ }, "node_modules/next-tick": { "version": "1.1.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "peer": true }, "node_modules/nice-try": { "version": "1.0.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "peer": true }, "node_modules/node-bitmap": { @@ -21428,7 +22449,8 @@ }, "node_modules/node-dir": { "version": "0.1.17", - "license": "MIT", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", "peer": true, "dependencies": { "minimatch": "^3.0.2" @@ -21439,6 +22461,8 @@ }, "node_modules/node-domexception": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "funding": [ { "type": "github", @@ -21449,7 +22473,6 @@ "url": "https://paypal.me/jimmywarting" } ], - "license": "MIT", "peer": true, "engines": { "node": ">=10.5.0" @@ -21457,7 +22480,8 @@ }, "node_modules/node-fetch": { "version": "2.6.8", - "license": "MIT", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", + "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -21491,7 +22515,8 @@ }, "node_modules/node-gyp": { "version": "8.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -21513,14 +22538,16 @@ }, "node_modules/node-gyp/node_modules/minipass": { "version": "5.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "engines": { "node": ">=8" } }, "node_modules/node-gyp/node_modules/tar": { "version": "6.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -21535,7 +22562,8 @@ }, "node_modules/node-gyp/node_modules/which": { "version": "2.0.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dependencies": { "isexe": "^2.0.0" }, @@ -21548,12 +22576,14 @@ }, "node_modules/node-gyp/node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/node-html-parser": { "version": "6.1.4", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.4.tgz", + "integrity": "sha512-3muP9Uy/Pz7bQa9TNYVQzWJhNZMqyCx7xJle8kz2/y1UgzAUyXXShc1IcPaJy6u07CE3K5rQcRwlvHzmlySRjg==", "dev": true, - "license": "MIT", "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" @@ -21634,7 +22664,8 @@ }, "node_modules/node-schedule": { "version": "2.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.1.tgz", + "integrity": "sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==", "peer": true, "dependencies": { "cron-parser": "^4.2.0", @@ -21647,7 +22678,8 @@ }, "node_modules/node.extend": { "version": "2.0.2", - "license": "(MIT OR GPL-2.0)", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.2.tgz", + "integrity": "sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==", "dependencies": { "has": "^1.0.3", "is": "^3.2.1" @@ -21958,7 +22990,8 @@ }, "node_modules/npm-registry-fetch": { "version": "12.0.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-12.0.2.tgz", + "integrity": "sha512-Df5QT3RaJnXYuOwtXBXS9BWs+tHH2olvkCLh6jcR/b/u3DvPMlp3J0TvvYwplPKxHMOwfg287PYih9QqaVFoKA==", "dependencies": { "make-fetch-happen": "^10.0.1", "minipass": "^3.1.6", @@ -21973,7 +23006,8 @@ }, "node_modules/npm-registry-fetch/node_modules/@npmcli/fs": { "version": "2.1.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" @@ -21984,7 +23018,9 @@ }, "node_modules/npm-registry-fetch/node_modules/@npmcli/move-file": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -21995,21 +23031,24 @@ }, "node_modules/npm-registry-fetch/node_modules/@tootallnate/once": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "engines": { "node": ">= 10" } }, "node_modules/npm-registry-fetch/node_modules/brace-expansion": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/npm-registry-fetch/node_modules/cacache": { "version": "16.1.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", @@ -22036,7 +23075,8 @@ }, "node_modules/npm-registry-fetch/node_modules/glob": { "version": "8.1.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -22053,7 +23093,8 @@ }, "node_modules/npm-registry-fetch/node_modules/http-proxy-agent": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -22065,14 +23106,16 @@ }, "node_modules/npm-registry-fetch/node_modules/lru-cache": { "version": "7.18.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "engines": { "node": ">=12" } }, "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { "version": "10.2.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", @@ -22097,7 +23140,8 @@ }, "node_modules/npm-registry-fetch/node_modules/make-fetch-happen/node_modules/minipass-fetch": { "version": "2.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", @@ -22112,7 +23156,8 @@ }, "node_modules/npm-registry-fetch/node_modules/minimatch": { "version": "5.1.6", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -22122,7 +23167,8 @@ }, "node_modules/npm-registry-fetch/node_modules/socks-proxy-agent": { "version": "7.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -22134,7 +23180,8 @@ }, "node_modules/npm-registry-fetch/node_modules/ssri": { "version": "9.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dependencies": { "minipass": "^3.1.1" }, @@ -22144,7 +23191,8 @@ }, "node_modules/npm-registry-fetch/node_modules/tar": { "version": "6.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -22159,14 +23207,16 @@ }, "node_modules/npm-registry-fetch/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "engines": { "node": ">=8" } }, "node_modules/npm-registry-fetch/node_modules/unique-filename": { "version": "2.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dependencies": { "unique-slug": "^3.0.0" }, @@ -22176,7 +23226,8 @@ }, "node_modules/npm-registry-fetch/node_modules/unique-slug": { "version": "3.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dependencies": { "imurmurhash": "^0.1.4" }, @@ -22186,11 +23237,13 @@ }, "node_modules/npm-registry-fetch/node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/npm-registry-utilities": { "version": "1.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/npm-registry-utilities/-/npm-registry-utilities-1.0.0.tgz", + "integrity": "sha512-9xYfSJy2IFQw1i6462EJzjChL9e65EfSo2Cw6kl0EFeDp05VvU+anrQk3Fc0d1MbVCq7rWIxeer89O9SUQ/uOg==", "peer": true, "dependencies": { "ext": "^1.6.0", @@ -22284,7 +23337,8 @@ }, "node_modules/object-hash": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "peer": true, "engines": { "node": ">= 6" @@ -22292,7 +23346,8 @@ }, "node_modules/object-inspect": { "version": "1.13.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -22316,7 +23371,8 @@ }, "node_modules/object.assign": { "version": "4.1.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -22332,7 +23388,8 @@ }, "node_modules/object.hasown": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", "peer": true, "dependencies": { "define-properties": "^1.1.4", @@ -22354,8 +23411,9 @@ }, "node_modules/object.values": { "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "dev": true, - "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.4", @@ -22370,7 +23428,8 @@ }, "node_modules/objectorarray": { "version": "1.0.5", - "license": "ISC" + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==" }, "node_modules/omggif": { "version": "1.0.10", @@ -22378,7 +23437,8 @@ }, "node_modules/on-exit-leak-free": { "version": "2.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", "engines": { "node": ">=14.0.0" } @@ -22422,7 +23482,8 @@ }, "node_modules/open": { "version": "8.4.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", "peer": true, "dependencies": { "define-lazy-prop": "^2.0.0", @@ -22438,7 +23499,8 @@ }, "node_modules/open/node_modules/is-wsl": { "version": "2.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "peer": true, "dependencies": { "is-docker": "^2.0.0" @@ -22472,7 +23534,8 @@ }, "node_modules/ora": { "version": "5.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "peer": true, "dependencies": { "bl": "^4.1.0", @@ -22521,7 +23584,8 @@ }, "node_modules/p-event": { "version": "4.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", "peer": true, "dependencies": { "p-timeout": "^3.1.0" @@ -22581,7 +23645,8 @@ }, "node_modules/p-memoize": { "version": "7.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-7.1.1.tgz", + "integrity": "sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA==", "peer": true, "dependencies": { "mimic-fn": "^4.0.0", @@ -22596,7 +23661,8 @@ }, "node_modules/p-memoize/node_modules/mimic-fn": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "peer": true, "engines": { "node": ">=12" @@ -22657,7 +23723,8 @@ }, "node_modules/pa11y": { "version": "6.1.1", - "license": "LGPL-3.0", + "resolved": "https://registry.npmjs.org/pa11y/-/pa11y-6.1.1.tgz", + "integrity": "sha512-2NzqA3D9CUlDWj8WuOI4fM2P0qM1d/IUxsRRpzCOfDT5eMR1oEgmUwW2TAk+f90ff/GVck0BewdYT4et4BANew==", "dependencies": { "axe-core": "^4.0.2", "bfj": "~7.0.2", @@ -22680,7 +23747,8 @@ }, "node_modules/pa11y-ci": { "version": "3.0.1", - "license": "LGPL-3.0", + "resolved": "https://registry.npmjs.org/pa11y-ci/-/pa11y-ci-3.0.1.tgz", + "integrity": "sha512-DUtEIhEG3Ofds7qRuplq0DdCb9doILRlzcRctFNzo4QUNmVy4iZfM3u51A9cqoPo2irCJZoo5BzfiFrcriY2IQ==", "dependencies": { "async": "~2.6.3", "cheerio": "~1.0.0-rc.10", @@ -22703,7 +23771,8 @@ }, "node_modules/pa11y-ci/node_modules/array-union": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dependencies": { "array-uniq": "^1.0.1" }, @@ -22713,14 +23782,16 @@ }, "node_modules/pa11y-ci/node_modules/async": { "version": "2.6.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dependencies": { "lodash": "^4.17.14" } }, "node_modules/pa11y-ci/node_modules/find-up": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -22731,7 +23802,8 @@ }, "node_modules/pa11y-ci/node_modules/globby": { "version": "6.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", @@ -22745,14 +23817,16 @@ }, "node_modules/pa11y-ci/node_modules/kleur": { "version": "4.1.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "engines": { "node": ">=6" } }, "node_modules/pa11y-ci/node_modules/locate-path": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dependencies": { "p-locate": "^4.1.0" }, @@ -22762,7 +23836,8 @@ }, "node_modules/pa11y-ci/node_modules/p-limit": { "version": "2.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dependencies": { "p-try": "^2.0.0" }, @@ -22775,7 +23850,8 @@ }, "node_modules/pa11y-ci/node_modules/p-locate": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dependencies": { "p-limit": "^2.2.0" }, @@ -22785,14 +23861,16 @@ }, "node_modules/pa11y-ci/node_modules/pify": { "version": "2.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "engines": { "node": ">=0.10.0" } }, "node_modules/pa11y-ci/node_modules/pkg-dir": { "version": "4.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dependencies": { "find-up": "^4.0.0" }, @@ -22802,8 +23880,10 @@ }, "node_modules/pa11y-ci/node_modules/puppeteer": { "version": "9.1.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-9.1.1.tgz", + "integrity": "sha512-W+nOulP2tYd/ZG99WuZC/I5ljjQQ7EUw/jQGcIb9eu8mDlZxNY2SgcJXTLG9h5gRvqA3uJOe4hZXYsd3EqioMw==", + "deprecated": "Version no longer supported. Upgrade to @latest", "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0", "devtools-protocol": "0.0.869402", @@ -22824,14 +23904,16 @@ }, "node_modules/pa11y/node_modules/commander": { "version": "8.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.0.0.tgz", + "integrity": "sha512-Xvf85aAtu6v22+E5hfVoLHqyul/jyxh91zvqk/ioJTQuJR7Z78n7H558vMPKanPSRgIEeZemT92I2g9Y8LPbSQ==", "engines": { "node": ">= 12" } }, "node_modules/pa11y/node_modules/find-up": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -22842,14 +23924,16 @@ }, "node_modules/pa11y/node_modules/kleur": { "version": "4.1.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "engines": { "node": ">=6" } }, "node_modules/pa11y/node_modules/locate-path": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dependencies": { "p-locate": "^4.1.0" }, @@ -22859,7 +23943,8 @@ }, "node_modules/pa11y/node_modules/p-limit": { "version": "2.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dependencies": { "p-try": "^2.0.0" }, @@ -22872,7 +23957,8 @@ }, "node_modules/pa11y/node_modules/p-locate": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dependencies": { "p-limit": "^2.2.0" }, @@ -22882,14 +23968,16 @@ }, "node_modules/pa11y/node_modules/p-timeout": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz", + "integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==", "engines": { "node": ">=10" } }, "node_modules/pa11y/node_modules/pkg-dir": { "version": "4.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dependencies": { "find-up": "^4.0.0" }, @@ -22899,8 +23987,10 @@ }, "node_modules/pa11y/node_modules/puppeteer": { "version": "9.1.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-9.1.1.tgz", + "integrity": "sha512-W+nOulP2tYd/ZG99WuZC/I5ljjQQ7EUw/jQGcIb9eu8mDlZxNY2SgcJXTLG9h5gRvqA3uJOe4hZXYsd3EqioMw==", + "deprecated": "Version no longer supported. Upgrade to @latest", "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0", "devtools-protocol": "0.0.869402", @@ -23336,8 +24426,9 @@ }, "node_modules/parse-diff": { "version": "0.9.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.9.0.tgz", + "integrity": "sha512-Jn+VZORAezkfOXR6B40EZcXxdJBamtgBpfeoFH6hxD+p0e74nVaCL9SWlQj1ggc8b6AexgPKlDiiE0CMMZDSbQ==", + "dev": true }, "node_modules/parse-github-repo-url": { "version": "1.4.1", @@ -23362,7 +24453,8 @@ }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "7.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", "dependencies": { "domhandler": "^5.0.2", "parse5": "^7.0.0" @@ -23373,7 +24465,8 @@ }, "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { "version": "7.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", "dependencies": { "entities": "^4.3.0" }, @@ -23435,7 +24528,8 @@ }, "node_modules/path-loader": { "version": "1.0.12", - "license": "MIT", + "resolved": "https://registry.npmjs.org/path-loader/-/path-loader-1.0.12.tgz", + "integrity": "sha512-n7oDG8B+k/p818uweWrOixY9/Dsr89o2TkCm6tOTex3fpdo2+BFDgR+KpB37mGKBRsBAlR8CIJMFN0OEy/7hIQ==", "peer": true, "dependencies": { "native-promise-only": "^0.8.1", @@ -23444,7 +24538,8 @@ }, "node_modules/path-loader/node_modules/form-data": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "peer": true, "dependencies": { "asynckit": "^0.4.0", @@ -23457,7 +24552,8 @@ }, "node_modules/path-loader/node_modules/formidable": { "version": "2.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.1.tgz", + "integrity": "sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ==", "peer": true, "dependencies": { "dezalgo": "^1.0.4", @@ -23471,7 +24567,8 @@ }, "node_modules/path-loader/node_modules/qs": { "version": "6.11.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "peer": true, "dependencies": { "side-channel": "^1.0.4" @@ -23485,7 +24582,9 @@ }, "node_modules/path-loader/node_modules/superagent": { "version": "7.1.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.6.tgz", + "integrity": "sha512-gZkVCQR1gy/oUXr+kxJMLDjla434KmSOKbx5iGD30Ql+AkJQ/YlPKECJy2nhqOsHLjGHzoDTXNSjhnvWhzKk7g==", + "deprecated": "Please downgrade to v7.1.5 if you need IE/ActiveXObject support OR upgrade to v8.0.0 as we no longer support IE and published an incorrect patch version (see https://github.com/visionmedia/superagent/issues/1731)", "peer": true, "dependencies": { "component-emitter": "^1.3.0", @@ -23517,7 +24616,8 @@ }, "node_modules/path2": { "version": "0.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/path2/-/path2-0.1.0.tgz", + "integrity": "sha512-TX+cz8Jk+ta7IvRy2FAej8rdlbrP0+uBIkP/5DTODez/AuL/vSb30KuAdDxGVREXzn8QfAiu5mJYJ1XjbOhEPA==", "peer": true }, "node_modules/pathval": { @@ -23544,7 +24644,8 @@ }, "node_modules/peek-readable": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", "peer": true, "engines": { "node": ">=8" @@ -23585,14 +24686,16 @@ }, "node_modules/pinkie": { "version": "2.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dependencies": { "pinkie": "^2.0.0" }, @@ -23602,7 +24705,8 @@ }, "node_modules/pino": { "version": "8.15.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.15.4.tgz", + "integrity": "sha512-3s+SfSxeugMt8QeBVXprIJAgXuGDeGuHBfquXKEXKnpghlXzMGMjoa8tOSyzz00iBfQX3xlZvm2yJQ+d6SrVsg==", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", @@ -23622,7 +24726,8 @@ }, "node_modules/pino-abstract-transport": { "version": "1.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", + "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" @@ -23630,6 +24735,8 @@ }, "node_modules/pino-abstract-transport/node_modules/buffer": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -23644,7 +24751,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -23652,7 +24758,8 @@ }, "node_modules/pino-abstract-transport/node_modules/readable-stream": { "version": "4.4.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -23666,14 +24773,16 @@ }, "node_modules/pino-abstract-transport/node_modules/split2": { "version": "4.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "engines": { "node": ">= 10.x" } }, "node_modules/pino-pretty": { "version": "10.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.2.2.tgz", + "integrity": "sha512-RvAdCQAU51MdVsJdvXX4Bipb52wwldXtOzlva1NT8q2d7tmgYWFIMLhoSnfx2Sr+Hi7BLGpR/n8wgrcq5G/ykA==", "peer": true, "dependencies": { "colorette": "^2.0.7", @@ -23697,6 +24806,8 @@ }, "node_modules/pino-pretty/node_modules/buffer": { "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -23711,7 +24822,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "peer": true, "dependencies": { "base64-js": "^1.3.1", @@ -23720,7 +24830,8 @@ }, "node_modules/pino-pretty/node_modules/dateformat": { "version": "4.6.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", "peer": true, "engines": { "node": "*" @@ -23728,7 +24839,8 @@ }, "node_modules/pino-pretty/node_modules/readable-stream": { "version": "4.4.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", "peer": true, "dependencies": { "abort-controller": "^3.0.0", @@ -23743,7 +24855,8 @@ }, "node_modules/pino-std-serializers": { "version": "6.2.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" }, "node_modules/pirates": { "version": "4.0.5", @@ -23792,7 +24905,8 @@ }, "node_modules/possible-typed-array-names": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "engines": { "node": ">= 0.4" } @@ -23815,7 +24929,8 @@ }, "node_modules/prettier": { "version": "2.8.8", - "license": "MIT", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "bin": { "prettier": "bin-prettier.js" }, @@ -23870,7 +24985,8 @@ }, "node_modules/process-utils": { "version": "4.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/process-utils/-/process-utils-4.0.0.tgz", + "integrity": "sha512-fMyMQbKCxX51YxR7YGCzPjLsU3yDzXFkP4oi1/Mt5Ixnk7GO/7uUTj8mrCHUwuvozWzI+V7QSJR9cZYnwNOZPg==", "peer": true, "dependencies": { "ext": "^1.4.0", @@ -23884,7 +25000,8 @@ }, "node_modules/process-warning": { "version": "2.2.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz", + "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==" }, "node_modules/progress": { "version": "2.0.3", @@ -23899,7 +25016,8 @@ }, "node_modules/promise-queue": { "version": "2.2.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz", + "integrity": "sha512-p/iXrPSVfnqPft24ZdNNLECw/UrtLTpT3jpAAMzl/o5/rDsGCPo3/CQS2611flL6LkoEJ3oQZw7C8Q80ZISXRQ==", "peer": true, "engines": { "node": ">= 0.8.0" @@ -23929,7 +25047,8 @@ }, "node_modules/protocolify": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/protocolify/-/protocolify-3.0.0.tgz", + "integrity": "sha512-PuvDJOkKJMVQx8jSNf8E5g0bJw/UTKm30mTjFHg4N30c8sefgA5Qr/f8INKqYBKfvP/MUSJrj+z1Smjbq4/3rQ==", "dependencies": { "file-url": "^3.0.0", "prepend-http": "^3.0.0" @@ -23940,7 +25059,8 @@ }, "node_modules/protocolify/node_modules/prepend-http": { "version": "3.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-3.0.1.tgz", + "integrity": "sha512-BLxfZh+m6UiAiCPZFJ4+vYoL7NrRs5XgCTRrjseATAggXhdZKKxn+JUNmuVYWY23bDHgaEHodxw8mnmtVEDtHw==", "engines": { "node": ">=8" } @@ -24028,11 +25148,10 @@ }, "node_modules/puppeteer": { "version": "18.1.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-18.1.0.tgz", + "integrity": "sha512-2RCVWIF+pZOSfksWlQU0Hh6CeUT5NYt66CDDgRyuReu6EvBAk1y+/Q7DuzYNvGChSecGMb7QPN0hkxAa3guAog==", + "deprecated": "< 19.4.0 is no longer supported", "hasInstallScript": true, - "license": "Apache-2.0", - "workspaces": [ - "packages/*" - ], "dependencies": { "cross-fetch": "3.1.5", "debug": "4.3.4", @@ -24052,11 +25171,13 @@ }, "node_modules/puppeteer/node_modules/devtools-protocol": { "version": "0.0.1045489", - "license": "BSD-3-Clause" + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1045489.tgz", + "integrity": "sha512-D+PTmWulkuQW4D1NTiCRCFxF7pQPn0hgp4YyX4wAQ6xYXKOadSWPR3ENGDQ47MW/Ewc9v2rpC/UEEGahgBYpSQ==" }, "node_modules/puppeteer/node_modules/ws": { "version": "8.9.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", + "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", "engines": { "node": ">=10.0.0" }, @@ -24136,7 +25257,8 @@ }, "node_modules/quick-format-unescaped": { "version": "4.0.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" }, "node_modules/quick-lru": { "version": "4.0.1", @@ -24393,7 +25515,8 @@ }, "node_modules/readable-web-to-node-stream": { "version": "3.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", "peer": true, "dependencies": { "readable-stream": "^3.6.0" @@ -24408,7 +25531,8 @@ }, "node_modules/readdir-glob": { "version": "1.1.2", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz", + "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", "peer": true, "dependencies": { "minimatch": "^5.1.0" @@ -24416,7 +25540,8 @@ }, "node_modules/readdir-glob/node_modules/brace-expansion": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "peer": true, "dependencies": { "balanced-match": "^1.0.0" @@ -24424,7 +25549,8 @@ }, "node_modules/readdir-glob/node_modules/minimatch": { "version": "5.1.6", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "peer": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -24445,7 +25571,8 @@ }, "node_modules/real-require": { "version": "0.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", "engines": { "node": ">= 12.13.0" } @@ -24545,7 +25672,8 @@ }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dependencies": { "call-bind": "^1.0.6", "define-properties": "^1.2.1", @@ -24633,8 +25761,9 @@ }, "node_modules/release-please": { "version": "15.0.0", + "resolved": "https://registry.npmjs.org/release-please/-/release-please-15.0.0.tgz", + "integrity": "sha512-xNN/+xMuShbcpyLY0Gliu1OGHsz8gTNZzl/8V7i7BlphOJR9M0QTbp1vBxiBuy1IVm9NJEZ8DVytYXBGSguc3A==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@conventional-commits/parser": "^0.4.1", "@google-automations/git-file-utils": "^1.2.0", @@ -24680,8 +25809,9 @@ }, "node_modules/release-please/node_modules/@octokit/endpoint": { "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.3.tgz", + "integrity": "sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "is-plain-object": "^5.0.0", @@ -24693,13 +25823,15 @@ }, "node_modules/release-please/node_modules/@octokit/openapi-types": { "version": "14.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-14.0.0.tgz", + "integrity": "sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==", + "dev": true }, "node_modules/release-please/node_modules/@octokit/request": { "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.2.tgz", + "integrity": "sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -24714,8 +25846,9 @@ }, "node_modules/release-please/node_modules/@octokit/request-error": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.2.tgz", + "integrity": "sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/types": "^8.0.0", "deprecation": "^2.0.0", @@ -24727,24 +25860,27 @@ }, "node_modules/release-please/node_modules/@octokit/types": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-8.0.0.tgz", + "integrity": "sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==", "dev": true, - "license": "MIT", "dependencies": { "@octokit/openapi-types": "^14.0.0" } }, "node_modules/release-please/node_modules/@tootallnate/once": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/release-please/node_modules/conventional-changelog-conventionalcommits": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", + "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", "dev": true, - "license": "ISC", "dependencies": { "compare-func": "^2.0.0", "lodash": "^4.17.15", @@ -24756,8 +25892,9 @@ }, "node_modules/release-please/node_modules/http-proxy-agent": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, - "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -24872,7 +26009,8 @@ }, "node_modules/resolve": { "version": "1.22.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -24887,7 +26025,8 @@ }, "node_modules/resolve-alpn": { "version": "1.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", "peer": true }, "node_modules/resolve-cwd": { @@ -24920,7 +26059,8 @@ }, "node_modules/resolve-pkg": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-2.0.0.tgz", + "integrity": "sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==", "dependencies": { "resolve-from": "^5.0.0" }, @@ -25051,6 +26191,8 @@ }, "node_modules/run-parallel-limit": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", + "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", "funding": [ { "type": "github", @@ -25065,7 +26207,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "peer": true, "dependencies": { "queue-microtask": "^1.2.2" @@ -25095,7 +26236,8 @@ }, "node_modules/safe-array-concat": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -25111,7 +26253,8 @@ }, "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", - "license": "MIT" + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "node_modules/safe-buffer": { "version": "5.1.2", @@ -25126,7 +26269,8 @@ }, "node_modules/safe-regex-test": { "version": "1.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -25156,7 +26300,8 @@ }, "node_modules/sax": { "version": "1.2.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", "peer": true }, "node_modules/scarlet": { @@ -25180,7 +26325,8 @@ }, "node_modules/secure-json-parse": { "version": "2.7.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", "peer": true }, "node_modules/seedrandom": { @@ -25189,7 +26335,8 @@ }, "node_modules/seek-bzip": { "version": "1.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", "peer": true, "dependencies": { "commander": "^2.8.1" @@ -25201,12 +26348,14 @@ }, "node_modules/seek-bzip/node_modules/commander": { "version": "2.20.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "peer": true }, "node_modules/semver": { "version": "7.3.7", - "license": "ISC", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -25242,7 +26391,8 @@ }, "node_modules/semver-regex": { "version": "3.1.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", + "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", "engines": { "node": ">=8" }, @@ -25283,8 +26433,9 @@ }, "node_modules/serverless": { "version": "3.27.0", + "resolved": "https://registry.npmjs.org/serverless/-/serverless-3.27.0.tgz", + "integrity": "sha512-+8EDo7x8IJxTj4KqQG71qpX7oq+EZy0NGm/04q3M5jK7L8rLowEtnzq82s93yeNSgmJSMopd3pTzuH9CCWkNMw==", "hasInstallScript": true, - "license": "MIT", "peer": true, "dependencies": { "@serverless/dashboard-plugin": "^6.2.3", @@ -25351,7 +26502,8 @@ }, "node_modules/serverless-offline": { "version": "12.0.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/serverless-offline/-/serverless-offline-12.0.4.tgz", + "integrity": "sha512-G256wDHI12vE0CJ0uTJMBlfnaN7o7td4GgClvQtuedt/n7vKoUfN0och+LybD6YVGsR5h1xpYjPPPLy2QFqWaA==", "peer": true, "dependencies": { "@aws-sdk/client-lambda": "^3.241.0", @@ -25390,12 +26542,14 @@ }, "node_modules/serverless-offline/node_modules/@types/retry": { "version": "0.12.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==", "peer": true }, "node_modules/serverless-offline/node_modules/ansi-regex": { "version": "6.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "peer": true, "engines": { "node": ">=12" @@ -25406,7 +26560,8 @@ }, "node_modules/serverless-offline/node_modules/ansi-styles": { "version": "6.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "peer": true, "engines": { "node": ">=12" @@ -25417,7 +26572,8 @@ }, "node_modules/serverless-offline/node_modules/boxen": { "version": "7.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.1.tgz", + "integrity": "sha512-8k2eH6SRAK00NDl1iX5q17RJ8rfl53TajdYxE3ssMLehbg487dEVgsad4pIsZb/QqBgYWIl6JOauMTLGX2Kpkw==", "peer": true, "dependencies": { "ansi-align": "^3.0.1", @@ -25438,7 +26594,8 @@ }, "node_modules/serverless-offline/node_modules/camelcase": { "version": "7.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", "peer": true, "engines": { "node": ">=14.16" @@ -25449,7 +26606,8 @@ }, "node_modules/serverless-offline/node_modules/chalk": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", "peer": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -25460,7 +26618,8 @@ }, "node_modules/serverless-offline/node_modules/cli-boxes": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "peer": true, "engines": { "node": ">=10" @@ -25471,7 +26630,8 @@ }, "node_modules/serverless-offline/node_modules/cross-spawn": { "version": "7.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "peer": true, "dependencies": { "path-key": "^3.1.0", @@ -25484,7 +26644,8 @@ }, "node_modules/serverless-offline/node_modules/data-uri-to-buffer": { "version": "4.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "peer": true, "engines": { "node": ">= 12" @@ -25492,12 +26653,14 @@ }, "node_modules/serverless-offline/node_modules/emoji-regex": { "version": "9.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "peer": true }, "node_modules/serverless-offline/node_modules/execa": { "version": "6.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", "peer": true, "dependencies": { "cross-spawn": "^7.0.3", @@ -25519,7 +26682,8 @@ }, "node_modules/serverless-offline/node_modules/fs-extra": { "version": "11.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", "peer": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -25532,7 +26696,8 @@ }, "node_modules/serverless-offline/node_modules/human-signals": { "version": "3.0.1", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", "peer": true, "engines": { "node": ">=12.20.0" @@ -25540,7 +26705,8 @@ }, "node_modules/serverless-offline/node_modules/is-stream": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "peer": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -25551,7 +26717,8 @@ }, "node_modules/serverless-offline/node_modules/is-wsl": { "version": "2.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "peer": true, "dependencies": { "is-docker": "^2.0.0" @@ -25562,7 +26729,8 @@ }, "node_modules/serverless-offline/node_modules/mimic-fn": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "peer": true, "engines": { "node": ">=12" @@ -25573,7 +26741,8 @@ }, "node_modules/serverless-offline/node_modules/node-fetch": { "version": "3.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", + "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", "peer": true, "dependencies": { "data-uri-to-buffer": "^4.0.0", @@ -25590,7 +26759,8 @@ }, "node_modules/serverless-offline/node_modules/npm-run-path": { "version": "5.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", "peer": true, "dependencies": { "path-key": "^4.0.0" @@ -25604,7 +26774,8 @@ }, "node_modules/serverless-offline/node_modules/npm-run-path/node_modules/path-key": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "peer": true, "engines": { "node": ">=12" @@ -25615,7 +26786,8 @@ }, "node_modules/serverless-offline/node_modules/onetime": { "version": "6.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "peer": true, "dependencies": { "mimic-fn": "^4.0.0" @@ -25629,7 +26801,8 @@ }, "node_modules/serverless-offline/node_modules/p-retry": { "version": "5.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-5.1.2.tgz", + "integrity": "sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==", "peer": true, "dependencies": { "@types/retry": "0.12.1", @@ -25644,7 +26817,8 @@ }, "node_modules/serverless-offline/node_modules/retry": { "version": "0.13.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "peer": true, "engines": { "node": ">= 4" @@ -25652,7 +26826,8 @@ }, "node_modules/serverless-offline/node_modules/shebang-command": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "peer": true, "dependencies": { "shebang-regex": "^3.0.0" @@ -25663,7 +26838,8 @@ }, "node_modules/serverless-offline/node_modules/shebang-regex": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "peer": true, "engines": { "node": ">=8" @@ -25671,7 +26847,8 @@ }, "node_modules/serverless-offline/node_modules/string-width": { "version": "5.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "peer": true, "dependencies": { "eastasianwidth": "^0.2.0", @@ -25687,7 +26864,8 @@ }, "node_modules/serverless-offline/node_modules/strip-ansi": { "version": "7.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", "peer": true, "dependencies": { "ansi-regex": "^6.0.1" @@ -25701,7 +26879,8 @@ }, "node_modules/serverless-offline/node_modules/strip-final-newline": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "peer": true, "engines": { "node": ">=12" @@ -25712,7 +26891,8 @@ }, "node_modules/serverless-offline/node_modules/which": { "version": "2.0.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "peer": true, "dependencies": { "isexe": "^2.0.0" @@ -25726,7 +26906,8 @@ }, "node_modules/serverless-offline/node_modules/widest-line": { "version": "4.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", "peer": true, "dependencies": { "string-width": "^5.0.1" @@ -25740,7 +26921,8 @@ }, "node_modules/serverless-offline/node_modules/wrap-ansi": { "version": "8.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "peer": true, "dependencies": { "ansi-styles": "^6.1.0", @@ -25756,7 +26938,8 @@ }, "node_modules/serverless-offline/node_modules/ws": { "version": "8.12.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", + "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", "peer": true, "engines": { "node": ">=10.0.0" @@ -25776,7 +26959,8 @@ }, "node_modules/serverless/node_modules/@sindresorhus/is": { "version": "4.6.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "peer": true, "engines": { "node": ">=10" @@ -25787,7 +26971,8 @@ }, "node_modules/serverless/node_modules/@szmarczak/http-timer": { "version": "4.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "peer": true, "dependencies": { "defer-to-connect": "^2.0.0" @@ -25798,7 +26983,8 @@ }, "node_modules/serverless/node_modules/ajv": { "version": "8.12.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -25813,7 +26999,8 @@ }, "node_modules/serverless/node_modules/archiver": { "version": "5.3.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", + "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -25830,7 +27017,8 @@ }, "node_modules/serverless/node_modules/cacheable-request": { "version": "7.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", "peer": true, "dependencies": { "clone-response": "^1.0.2", @@ -25847,13 +27035,14 @@ }, "node_modules/serverless/node_modules/ci-info": { "version": "3.7.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", + "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/sibiraj-s" } ], - "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -25861,7 +27050,8 @@ }, "node_modules/serverless/node_modules/compress-commons": { "version": "4.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", @@ -25875,7 +27065,8 @@ }, "node_modules/serverless/node_modules/crc32-stream": { "version": "4.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", "peer": true, "dependencies": { "crc-32": "^1.2.0", @@ -25887,7 +27078,8 @@ }, "node_modules/serverless/node_modules/decompress-response": { "version": "6.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "peer": true, "dependencies": { "mimic-response": "^3.1.0" @@ -25901,7 +27093,8 @@ }, "node_modules/serverless/node_modules/defer-to-connect": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "peer": true, "engines": { "node": ">=10" @@ -25909,7 +27102,8 @@ }, "node_modules/serverless/node_modules/get-stream": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "peer": true, "dependencies": { "pump": "^3.0.0" @@ -25923,7 +27117,8 @@ }, "node_modules/serverless/node_modules/got": { "version": "11.8.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "peer": true, "dependencies": { "@sindresorhus/is": "^4.0.0", @@ -25947,17 +27142,20 @@ }, "node_modules/serverless/node_modules/json-buffer": { "version": "3.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "peer": true }, "node_modules/serverless/node_modules/json-schema-traverse": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "peer": true }, "node_modules/serverless/node_modules/keyv": { "version": "4.5.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", "peer": true, "dependencies": { "json-buffer": "3.0.1" @@ -25965,7 +27163,8 @@ }, "node_modules/serverless/node_modules/lowercase-keys": { "version": "2.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "peer": true, "engines": { "node": ">=8" @@ -25973,7 +27172,8 @@ }, "node_modules/serverless/node_modules/lru-cache": { "version": "6.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "peer": true, "dependencies": { "yallist": "^4.0.0" @@ -25984,7 +27184,8 @@ }, "node_modules/serverless/node_modules/mimic-response": { "version": "3.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "peer": true, "engines": { "node": ">=10" @@ -25995,7 +27196,8 @@ }, "node_modules/serverless/node_modules/minipass": { "version": "4.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.1.tgz", + "integrity": "sha512-V9esFpNbK0arbN3fm2sxDKqMYgIp7XtVdE4Esj+PE4Qaaxdg1wIw48ITQIOn1sc8xXSmUviVL3cyjMqPlrVkiA==", "peer": true, "engines": { "node": ">=8" @@ -26003,7 +27205,8 @@ }, "node_modules/serverless/node_modules/node-fetch": { "version": "2.6.9", - "license": "MIT", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", "peer": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -26022,7 +27225,8 @@ }, "node_modules/serverless/node_modules/normalize-url": { "version": "6.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "peer": true, "engines": { "node": ">=10" @@ -26033,7 +27237,8 @@ }, "node_modules/serverless/node_modules/p-cancelable": { "version": "2.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "peer": true, "engines": { "node": ">=8" @@ -26041,7 +27246,8 @@ }, "node_modules/serverless/node_modules/responselike": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", "peer": true, "dependencies": { "lowercase-keys": "^2.0.0" @@ -26052,7 +27258,8 @@ }, "node_modules/serverless/node_modules/semver": { "version": "7.3.8", - "license": "ISC", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "peer": true, "dependencies": { "lru-cache": "^6.0.0" @@ -26066,7 +27273,8 @@ }, "node_modules/serverless/node_modules/supports-color": { "version": "8.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -26080,7 +27288,8 @@ }, "node_modules/serverless/node_modules/tar": { "version": "6.1.13", - "license": "ISC", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "peer": true, "dependencies": { "chownr": "^2.0.0", @@ -26096,12 +27305,14 @@ }, "node_modules/serverless/node_modules/tr46": { "version": "0.0.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "peer": true }, "node_modules/serverless/node_modules/uuid": { "version": "9.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", "peer": true, "bin": { "uuid": "dist/bin/uuid" @@ -26109,12 +27320,14 @@ }, "node_modules/serverless/node_modules/webidl-conversions": { "version": "3.0.1", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "peer": true }, "node_modules/serverless/node_modules/whatwg-url": { "version": "5.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "peer": true, "dependencies": { "tr46": "~0.0.3", @@ -26123,12 +27336,14 @@ }, "node_modules/serverless/node_modules/yallist": { "version": "4.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "peer": true }, "node_modules/serverless/node_modules/zip-stream": { "version": "4.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -26145,7 +27360,8 @@ }, "node_modules/set-function-length": { "version": "1.2.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -26160,7 +27376,8 @@ }, "node_modules/set-function-name": { "version": "2.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -26258,7 +27475,8 @@ }, "node_modules/simple-git": { "version": "3.17.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.17.0.tgz", + "integrity": "sha512-JozI/s8jr3nvLd9yn2jzPVHnhVzt7t7QWfcIoDcqRIGN+f1IINGv52xoZti2kkYfoRhhRvzMSNPfogHMp97rlw==", "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", @@ -26446,7 +27664,8 @@ }, "node_modules/sonic-boom": { "version": "3.5.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.5.0.tgz", + "integrity": "sha512-02A0wEmj4d3aEIW/Sp6LMP1dNcG5cYmQPjhgtytIXa9tNmFZx3ragUPFmyBdgdM0yJJVSWwlLLEVHgrYfA0wtQ==", "dependencies": { "atomic-sleep": "^1.0.0" } @@ -26464,7 +27683,8 @@ }, "node_modules/sort-keys-length": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", "peer": true, "dependencies": { "sort-keys": "^1.0.0" @@ -26475,7 +27695,8 @@ }, "node_modules/sort-keys-length/node_modules/sort-keys": { "version": "1.1.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", "peer": true, "dependencies": { "is-plain-obj": "^1.0.0" @@ -26486,7 +27707,8 @@ }, "node_modules/sorted-array-functions": { "version": "1.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", + "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==", "peer": true }, "node_modules/source-list-map": { @@ -26525,8 +27747,9 @@ }, "node_modules/spawk": { "version": "1.8.1", + "resolved": "https://registry.npmjs.org/spawk/-/spawk-1.8.1.tgz", + "integrity": "sha512-Ws7F450Kz6u/zxVjNQqZwuiOfs+603qyK3vkeY5Rjgp5wnoK0d/7t5iliXKxDm1Pf/eJr3CcynNA3mAqjIugXA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12.0.0" } @@ -26620,7 +27843,8 @@ }, "node_modules/sprintf-kit": { "version": "2.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.1.tgz", + "integrity": "sha512-2PNlcs3j5JflQKcg4wpdqpZ+AjhQJ2OZEo34NXDtlB0tIPG84xaaXhpA8XFacFiwjKA4m49UOYG83y3hbMn/gQ==", "peer": true, "dependencies": { "es5-ext": "^0.10.53" @@ -26651,7 +27875,8 @@ }, "node_modules/ssri": { "version": "8.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "dependencies": { "minipass": "^3.1.1" }, @@ -26845,7 +28070,8 @@ }, "node_modules/stream-promise": { "version": "3.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/stream-promise/-/stream-promise-3.2.0.tgz", + "integrity": "sha512-P+7muTGs2C8yRcgJw/PPt61q7O517tDHiwYEzMWo1GSBCcZedUMT/clz7vUNsSxFphIlJ6QUL4GexQKlfJoVtA==", "peer": true, "dependencies": { "2-thenable": "^1.0.0", @@ -26855,7 +28081,8 @@ }, "node_modules/stream-promise/node_modules/is-stream": { "version": "1.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "peer": true, "engines": { "node": ">=0.10.0" @@ -26899,8 +28126,7 @@ }, "node_modules/string-length": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "license": "MIT", "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -26923,7 +28149,8 @@ }, "node_modules/string.prototype.trim": { "version": "1.2.9", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -26939,7 +28166,8 @@ }, "node_modules/string.prototype.trimend": { "version": "1.0.8", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -26951,7 +28179,8 @@ }, "node_modules/string.prototype.trimstart": { "version": "1.0.8", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -27002,7 +28231,8 @@ }, "node_modules/strip-dirs": { "version": "2.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", "peer": true, "dependencies": { "is-natural-number": "^4.0.1" @@ -27038,7 +28268,8 @@ }, "node_modules/strip-outer": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "peer": true, "dependencies": { "escape-string-regexp": "^1.0.2" @@ -27049,7 +28280,8 @@ }, "node_modules/strip-outer/node_modules/escape-string-regexp": { "version": "1.0.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "peer": true, "engines": { "node": ">=0.8.0" @@ -27057,7 +28289,8 @@ }, "node_modules/strnum": { "version": "1.0.5", - "license": "MIT" + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, "node_modules/strong-cluster-control": { "version": "2.2.4", @@ -27099,7 +28332,8 @@ }, "node_modules/strtok3": { "version": "6.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", "peer": true, "dependencies": { "@tokenizer/token": "^0.3.0", @@ -27175,7 +28409,8 @@ }, "node_modules/tar": { "version": "4.4.19", - "license": "ISC", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", "dependencies": { "chownr": "^1.1.4", "fs-minipass": "^1.2.7", @@ -27191,7 +28426,8 @@ }, "node_modules/tar-fs": { "version": "2.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -27201,7 +28437,8 @@ }, "node_modules/tar-fs/node_modules/chownr": { "version": "1.1.4", - "license": "ISC" + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "node_modules/tar-stream": { "version": "2.2.0", @@ -27219,18 +28456,21 @@ }, "node_modules/tar/node_modules/chownr": { "version": "1.1.4", - "license": "ISC" + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "node_modules/tar/node_modules/fs-minipass": { "version": "1.2.7", - "license": "ISC", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dependencies": { "minipass": "^2.6.0" } }, "node_modules/tar/node_modules/minipass": { "version": "2.9.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dependencies": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -27238,14 +28478,16 @@ }, "node_modules/tar/node_modules/minizlib": { "version": "1.3.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dependencies": { "minipass": "^2.9.0" } }, "node_modules/tar/node_modules/mkdirp": { "version": "0.5.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dependencies": { "minimist": "^1.2.6" }, @@ -27255,6 +28497,8 @@ }, "node_modules/tar/node_modules/safe-buffer": { "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -27268,12 +28512,12 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/tar/node_modules/yallist": { "version": "3.1.1", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/tcp-port-used": { "version": "1.0.2", @@ -27300,8 +28544,9 @@ }, "node_modules/temp": { "version": "0.9.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", + "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, - "license": "MIT", "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -27312,8 +28557,9 @@ }, "node_modules/temp/node_modules/mkdirp": { "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, - "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -27323,8 +28569,9 @@ }, "node_modules/temp/node_modules/rimraf": { "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, - "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -27334,7 +28581,8 @@ }, "node_modules/terser": { "version": "4.8.1", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dependencies": { "commander": "^2.20.0", "source-map": "~0.6.1", @@ -27470,14 +28718,16 @@ }, "node_modules/thenify": { "version": "3.3.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dependencies": { "any-promise": "^1.0.0" } }, "node_modules/thenify-all": { "version": "1.6.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -27487,7 +28737,8 @@ }, "node_modules/thread-stream": { "version": "2.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", + "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", "dependencies": { "real-require": "^0.2.0" } @@ -27516,7 +28767,8 @@ }, "node_modules/timers-ext": { "version": "0.1.7", - "license": "ISC", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", "peer": true, "dependencies": { "es5-ext": "~0.10.46", @@ -27543,7 +28795,8 @@ }, "node_modules/to-buffer": { "version": "1.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", "peer": true }, "node_modules/to-fast-properties": { @@ -27687,7 +28940,8 @@ }, "node_modules/token-types": { "version": "4.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", "peer": true, "dependencies": { "@tokenizer/token": "^0.3.0", @@ -27725,7 +28979,8 @@ }, "node_modules/traverse": { "version": "0.6.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", + "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -27741,7 +28996,8 @@ }, "node_modules/trim-repeated": { "version": "1.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "peer": true, "dependencies": { "escape-string-regexp": "^1.0.2" @@ -27752,7 +29008,8 @@ }, "node_modules/trim-repeated/node_modules/escape-string-regexp": { "version": "1.0.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "peer": true, "engines": { "node": ">=0.8.0" @@ -27764,7 +29021,8 @@ }, "node_modules/tryer": { "version": "1.0.1", - "license": "MIT" + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" }, "node_modules/ts-jest": { "version": "29.1.2", @@ -27928,8 +29186,9 @@ }, "node_modules/tsconfig-paths/node_modules/json5": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, - "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -27951,8 +29210,9 @@ }, "node_modules/tsutils": { "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, - "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -27983,7 +29243,8 @@ }, "node_modules/type": { "version": "2.7.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", "peer": true }, "node_modules/type-check": { @@ -28006,7 +29267,8 @@ }, "node_modules/type-fest": { "version": "3.6.0", - "license": "(MIT OR CC0-1.0)", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.6.0.tgz", + "integrity": "sha512-RqTRtKTzvPpNdDUp1dVkKQRunlPITk4mXeqFlAZoJsS+fLRn8AdPK0TcQDumGayhU7fjlBfiBjsq3pe3rIfXZQ==", "engines": { "node": ">=14.16" }, @@ -28016,7 +29278,8 @@ }, "node_modules/typed-array-buffer": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -28028,7 +29291,8 @@ }, "node_modules/typed-array-byte-length": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -28045,7 +29309,8 @@ }, "node_modules/typed-array-byte-offset": { "version": "1.0.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -28063,7 +29328,8 @@ }, "node_modules/typed-array-length": { "version": "1.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -28131,7 +29397,8 @@ }, "node_modules/unbzip2-stream": { "version": "1.4.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" @@ -28139,6 +29406,8 @@ }, "node_modules/unbzip2-stream/node_modules/buffer": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -28153,7 +29422,6 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -28171,7 +29439,8 @@ }, "node_modules/uni-global": { "version": "1.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/uni-global/-/uni-global-1.0.0.tgz", + "integrity": "sha512-WWM3HP+siTxzIWPNUg7hZ4XO8clKi6NoCAJJWnuRL+BAqyFXF8gC03WNyTefGoUXYc47uYgXxpKLIEvo65PEHw==", "peer": true, "dependencies": { "type": "^2.5.0" @@ -28351,7 +29620,8 @@ }, "node_modules/untildify": { "version": "4.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", "peer": true, "engines": { "node": ">=8" @@ -28539,7 +29809,8 @@ }, "node_modules/velocityjs": { "version": "2.0.6", - "license": "MIT", + "resolved": "https://registry.npmjs.org/velocityjs/-/velocityjs-2.0.6.tgz", + "integrity": "sha512-QMYLeYLBX6eqekCin3OPmDAHapaUx3foNFE264ml1/yxRZ8TUUlI1+u6rtN4E8tKNqwzpRPeNgJtjLbgRNK4fw==", "peer": true, "dependencies": { "debug": "^4.3.3" @@ -28975,7 +30246,8 @@ }, "node_modules/wcwidth": { "version": "1.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "peer": true, "dependencies": { "defaults": "^1.0.3" @@ -28983,7 +30255,8 @@ }, "node_modules/web-streams-polyfill": { "version": "3.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", "peer": true, "engines": { "node": ">= 8" @@ -29370,7 +30643,8 @@ }, "node_modules/which-typed-array": { "version": "1.1.15", - "license": "MIT", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -29408,7 +30682,8 @@ }, "node_modules/winston": { "version": "3.13.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.13.0.tgz", + "integrity": "sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", @@ -29428,7 +30703,8 @@ }, "node_modules/winston-transport": { "version": "4.7.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", "dependencies": { "logform": "^2.3.2", "readable-stream": "^3.6.0", @@ -29440,7 +30716,8 @@ }, "node_modules/winston/node_modules/@colors/colors": { "version": "1.6.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", "engines": { "node": ">=0.1.90" } @@ -29595,7 +30872,8 @@ }, "node_modules/xml2js": { "version": "0.4.19", - "license": "MIT", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", "peer": true, "dependencies": { "sax": ">=0.6.0", @@ -29604,7 +30882,8 @@ }, "node_modules/xmlbuilder": { "version": "9.0.7", - "license": "MIT", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", "peer": true, "engines": { "node": ">=4.0" @@ -29639,19 +30918,22 @@ }, "node_modules/yaml": { "version": "1.10.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "engines": { "node": ">= 6" } }, "node_modules/yaml-ast-parser": { "version": "0.0.43", - "license": "Apache-2.0", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", "peer": true }, "node_modules/yamljs": { "version": "0.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -29664,7 +30946,8 @@ }, "node_modules/yamljs/node_modules/argparse": { "version": "1.0.10", - "license": "MIT", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "peer": true, "dependencies": { "sprintf-js": "~1.0.2" @@ -29784,15 +31067,17 @@ }, "node_modules/zod": { "version": "3.22.4", - "license": "MIT", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, "node_modules/zod2md": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/zod2md/-/zod2md-0.1.2.tgz", + "integrity": "sha512-+pWpY+4yLKCnNyLeVi7RQLfPkKuMqbSwiFPy83bbvM+ZYi+B54lCcBPDBcRecrSH4VMxD7gkIeH8mKr4/vF9Bg==", "dev": true, - "license": "MIT", "dependencies": { "@commander-js/extra-typings": "^12.0.0", "bundle-require": "^4.0.2", @@ -29808,16 +31093,18 @@ }, "node_modules/zod2md/node_modules/@commander-js/extra-typings": { "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commander-js/extra-typings/-/extra-typings-12.0.1.tgz", + "integrity": "sha512-OvkMobb1eMqOCuJdbuSin/KJkkZr7n24/UNV+Lcz/0Dhepf3r2p9PaGwpRpAWej7A+gQnny4h8mGhpFl4giKkg==", "dev": true, - "license": "MIT", "peerDependencies": { "commander": "~12.0.0" } }, "node_modules/zod2md/node_modules/commander": { "version": "12.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz", + "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" } @@ -29850,7 +31137,8 @@ }, "plugins/babel/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/backend-app": { "name": "@dotcom-tool-kit/backend-app", @@ -29960,7 +31248,8 @@ }, "plugins/circleci-deploy/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/circleci-heroku": { "name": "@dotcom-tool-kit/circleci-heroku", @@ -29981,7 +31270,8 @@ }, "plugins/circleci-heroku/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/circleci-npm": { "name": "@dotcom-tool-kit/circleci-npm", @@ -30002,11 +31292,13 @@ }, "plugins/circleci-npm/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/circleci/node_modules/@jest/schemas": { "version": "29.4.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dependencies": { "@sinclair/typebox": "^0.25.16" }, @@ -30016,11 +31308,13 @@ }, "plugins/circleci/node_modules/@sinclair/typebox": { "version": "0.25.24", - "license": "MIT" + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" }, "plugins/circleci/node_modules/ansi-styles": { "version": "5.2.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "engines": { "node": ">=10" }, @@ -30030,14 +31324,16 @@ }, "plugins/circleci/node_modules/diff-sequences": { "version": "29.4.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "plugins/circleci/node_modules/jest-diff": { "version": "29.5.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", @@ -30050,14 +31346,16 @@ }, "plugins/circleci/node_modules/jest-get-type": { "version": "29.4.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "plugins/circleci/node_modules/pretty-format": { "version": "29.5.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dependencies": { "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", @@ -30069,15 +31367,18 @@ }, "plugins/circleci/node_modules/react-is": { "version": "18.2.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "plugins/circleci/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/circleci/node_modules/type-fest": { "version": "3.5.4", - "license": "(MIT OR CC0-1.0)", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.5.4.tgz", + "integrity": "sha512-/Je22Er4LPoln256pcLzj73MUmPrTWg8u4WB1RlxaDl0idJOfD1r259VtKOinp4xLJqJ9zYVMuWOun6Ssp7boA==", "engines": { "node": ">=14.16" }, @@ -30087,7 +31388,8 @@ }, "plugins/circleci/node_modules/yaml": { "version": "2.1.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", + "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", "engines": { "node": ">= 14" } @@ -30337,7 +31639,8 @@ }, "plugins/eslint/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/eslint/node_modules/which": { "version": "2.0.2", @@ -30407,7 +31710,8 @@ }, "plugins/heroku/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/husky-npm": { "name": "@dotcom-tool-kit/husky-npm", @@ -30428,7 +31732,8 @@ }, "plugins/husky-npm/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/jest": { "name": "@dotcom-tool-kit/jest", @@ -30454,7 +31759,8 @@ }, "plugins/jest/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/lint-staged": { "name": "@dotcom-tool-kit/lint-staged", @@ -30495,7 +31801,8 @@ }, "plugins/lint-staged-npm/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/lint-staged/node_modules/colorette": { "version": "1.4.0", @@ -30549,7 +31856,8 @@ }, "plugins/lint-staged/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/mocha": { "name": "@dotcom-tool-kit/mocha", @@ -30580,9 +31888,9 @@ }, "plugins/mocha/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, - "plugins/monorepo": {}, "plugins/n-test": { "name": "@dotcom-tool-kit/n-test", "version": "3.3.1", @@ -30610,8 +31918,9 @@ }, "plugins/n-test/node_modules/@financial-times/n-test": { "version": "6.1.0-beta.1", + "resolved": "https://registry.npmjs.org/@financial-times/n-test/-/n-test-6.1.0-beta.1.tgz", + "integrity": "sha512-xVCswU9R4MWKxtJ+xi9Ur9aZoBiqOvbtDbtD7bEBUMssHdRbs0xXsZNto2fDm18w7TicZZZZfMtbYS8Ob1snag==", "hasInstallScript": true, - "license": "ISC", "dependencies": { "chalk": "^2.3.0", "commander": "^3.0.0", @@ -30632,7 +31941,8 @@ }, "plugins/n-test/node_modules/ansi-styles": { "version": "3.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { "color-convert": "^1.9.0" }, @@ -30642,7 +31952,8 @@ }, "plugins/n-test/node_modules/chalk": { "version": "2.4.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -30654,36 +31965,42 @@ }, "plugins/n-test/node_modules/color-convert": { "version": "1.9.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { "color-name": "1.1.3" } }, "plugins/n-test/node_modules/color-name": { "version": "1.1.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "plugins/n-test/node_modules/commander": { "version": "3.0.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" }, "plugins/n-test/node_modules/escape-string-regexp": { "version": "1.0.5", - "license": "MIT", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { "node": ">=0.8.0" } }, "plugins/n-test/node_modules/has-flag": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { "node": ">=4" } }, "plugins/n-test/node_modules/supports-color": { "version": "5.5.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { "has-flag": "^3.0.0" }, @@ -30693,7 +32010,8 @@ }, "plugins/n-test/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/next-router": { "name": "@dotcom-tool-kit/next-router", @@ -30721,6 +32039,8 @@ }, "plugins/next-router/node_modules/@financial-times/n-flags-client": { "version": "14.0.1", + "resolved": "https://registry.npmjs.org/@financial-times/n-flags-client/-/n-flags-client-14.0.1.tgz", + "integrity": "sha512-gTwqo4Bzu9GQlGgaBF7U9B6cHt4YVPFPSBuyUNbUPB9TJOvdi7wY0TueBFmOOydcfuF1i2HRJeXP6foTfoBoWw==", "dependencies": { "@dotcom-reliability-kit/logger": "^2.2.6", "n-eager-fetch": "^7.0.0", @@ -30733,6 +32053,8 @@ }, "plugins/next-router/node_modules/ft-next-router": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ft-next-router/-/ft-next-router-3.0.0.tgz", + "integrity": "sha512-tQ8c45o2xEhbx/OGuWM/xEL5GkBnKg/mJ2+BVkBayHqvf0vFJCokPVq1Rqw84CQZnIRw/WMYe6j+eD9DEr54uA==", "dependencies": { "@dotcom-reliability-kit/crash-handler": "^3.0.2", "@dotcom-reliability-kit/log-error": "^3.1.0", @@ -30762,8 +32084,9 @@ } }, "plugins/next-router/node_modules/ft-poller": { - "version": "0.0.0", - "license": "MIT", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ft-poller/-/ft-poller-9.0.0.tgz", + "integrity": "sha512-oHo0nICYKdAxsHy66mKBojCddAHfXiR2gcF0hbMoIuDm6tLzXumwUgFcGMQ1EK5R0C2ZVwb20p6kumGP8qLusA==", "dependencies": { "@dotcom-reliability-kit/logger": "^2.2.7", "isomorphic-fetch": "^3.0.0", @@ -30776,7 +32099,8 @@ }, "plugins/next-router/node_modules/ft-poller/node_modules/isomorphic-fetch": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", "dependencies": { "node-fetch": "^2.6.1", "whatwg-fetch": "^3.4.1" @@ -30784,6 +32108,8 @@ }, "plugins/next-router/node_modules/n-eager-fetch": { "version": "7.1.0", + "resolved": "https://registry.npmjs.org/n-eager-fetch/-/n-eager-fetch-7.1.0.tgz", + "integrity": "sha512-tPlZDKf1Tzir0czXvu63wuZb5RDIP+Lpqq56dfVu06qJqerAedUp2LspFbKQfxBKZdwpnKf5R9NLLZhEfR5tlQ==", "dependencies": { "isomorphic-fetch": "^3.0.0", "npm-prepublish": "^1.2.2" @@ -30795,7 +32121,8 @@ }, "plugins/next-router/node_modules/n-eager-fetch/node_modules/isomorphic-fetch": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", "dependencies": { "node-fetch": "^2.6.1", "whatwg-fetch": "^3.4.1" @@ -30803,6 +32130,8 @@ }, "plugins/next-router/node_modules/next-metrics": { "version": "10.0.3", + "resolved": "https://registry.npmjs.org/next-metrics/-/next-metrics-10.0.3.tgz", + "integrity": "sha512-HtYrmL0h79Bho3oW423oQFEW9Piu+i++cgUNM/HUtU2xlWkNtOwhhp3gWz906PexfoB7qaLmE7zS+S8SY32Z3w==", "dependencies": { "@dotcom-reliability-kit/logger": "^2.2.6", "lodash": "^4.17.21", @@ -30815,7 +32144,8 @@ }, "plugins/next-router/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/node": { "name": "@dotcom-tool-kit/node", @@ -30843,7 +32173,8 @@ }, "plugins/node/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/nodemon": { "name": "@dotcom-tool-kit/nodemon", @@ -30872,7 +32203,8 @@ }, "plugins/nodemon/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/npm": { "name": "@dotcom-tool-kit/npm", @@ -30907,7 +32239,8 @@ }, "plugins/npm/node_modules/@npmcli/git": { "version": "2.1.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", + "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", "dependencies": { "@npmcli/promise-spawn": "^1.3.2", "lru-cache": "^6.0.0", @@ -30921,8 +32254,9 @@ }, "plugins/npm/node_modules/@types/libnpmpublish": { "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/libnpmpublish/-/libnpmpublish-4.0.6.tgz", + "integrity": "sha512-xI99EEgpr1R0hpLAKb52QbBYv8ZZa9FDiZS7LEVE6RevjkQHF3BflPR7Mo2F8yxMnqP6eoPkWE0bnWvDC/sA9A==", "dev": true, - "license": "MIT", "dependencies": { "@npm/types": "*", "@types/node-fetch": "*", @@ -30931,8 +32265,9 @@ }, "plugins/npm/node_modules/@types/tar": { "version": "6.1.11", + "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-ThA1WD8aDdVU4VLuyq5NEqriwXErF5gEIJeyT6gHBWU7JtSmW2a5qjNv3/vR82O20mW+1vhmeZJfBQPT3HCugg==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*", "minipass": "^4.0.0" @@ -30940,15 +32275,17 @@ }, "plugins/npm/node_modules/@types/tar/node_modules/minipass": { "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", "dev": true, - "license": "ISC", "engines": { "node": ">=8" } }, "plugins/npm/node_modules/ignore-walk": { "version": "4.0.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", + "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", "dependencies": { "minimatch": "^3.0.4" }, @@ -30958,7 +32295,8 @@ }, "plugins/npm/node_modules/lru-cache": { "version": "6.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dependencies": { "yallist": "^4.0.0" }, @@ -30968,7 +32306,8 @@ }, "plugins/npm/node_modules/npm-install-checks": { "version": "4.0.0", - "license": "BSD-2-Clause", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", "dependencies": { "semver": "^7.1.1" }, @@ -30978,7 +32317,8 @@ }, "plugins/npm/node_modules/npm-packlist": { "version": "3.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", + "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", "dependencies": { "glob": "^7.1.6", "ignore-walk": "^4.0.1", @@ -30994,7 +32334,8 @@ }, "plugins/npm/node_modules/npm-pick-manifest": { "version": "6.1.1", - "license": "ISC", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", + "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", "dependencies": { "npm-install-checks": "^4.0.0", "npm-normalize-package-bin": "^1.0.1", @@ -31004,7 +32345,8 @@ }, "plugins/npm/node_modules/pacote": { "version": "12.0.3", - "license": "ISC", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-12.0.3.tgz", + "integrity": "sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow==", "dependencies": { "@npmcli/git": "^2.1.0", "@npmcli/installed-package-contents": "^1.0.6", @@ -31035,7 +32377,8 @@ }, "plugins/npm/node_modules/pacote/node_modules/tar": { "version": "6.2.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -31050,18 +32393,21 @@ }, "plugins/npm/node_modules/pacote/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "license": "ISC", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "engines": { "node": ">=8" } }, "plugins/npm/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/npm/node_modules/which": { "version": "2.0.2", - "license": "ISC", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dependencies": { "isexe": "^2.0.0" }, @@ -31074,7 +32420,8 @@ }, "plugins/npm/node_modules/yallist": { "version": "4.0.0", - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "plugins/pa11y": { "name": "@dotcom-tool-kit/pa11y", @@ -31098,7 +32445,8 @@ }, "plugins/pa11y/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/package-json-hook": { "name": "@dotcom-tool-kit/package-json-hook", @@ -31129,7 +32477,8 @@ }, "plugins/package-json-hook/node_modules/tslib": { "version": "2.6.2", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "plugins/prettier": { "name": "@dotcom-tool-kit/prettier", @@ -31159,12 +32508,33 @@ }, "plugins/prettier/node_modules/@types/prettier": { "version": "2.7.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true }, "plugins/prettier/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "plugins/secret-squirrel": { + "name": "@dotcom-tool-kit/secret-squirrel", + "version": "2.1.4", + "extraneous": true, + "license": "ISC", + "dependencies": { + "@dotcom-tool-kit/logger": "^3.2.0", + "@dotcom-tool-kit/types": "^3.4.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": "16.x || 18.x", + "npm": "7.x || 8.x || 9.x" + }, + "peerDependencies": { + "@financial-times/secret-squirrel": "2.x", + "dotcom-tool-kit": "3.x" + } }, "plugins/serverless": { "name": "@dotcom-tool-kit/serverless", @@ -31194,7 +32564,8 @@ }, "plugins/serverless/node_modules/tslib": { "version": "2.5.0", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "plugins/typescript": { "name": "@dotcom-tool-kit/typescript", @@ -31221,8 +32592,9 @@ }, "plugins/typescript/node_modules/@babel/code-frame": { "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, - "license": "MIT", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -31232,8 +32604,9 @@ }, "plugins/typescript/node_modules/@jest/environment": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", + "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", "dev": true, - "license": "MIT", "dependencies": { "@jest/fake-timers": "^29.3.1", "@jest/types": "^29.3.1", @@ -31246,8 +32619,9 @@ }, "plugins/typescript/node_modules/@jest/fake-timers": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", + "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", "dev": true, - "license": "MIT", "dependencies": { "@jest/types": "^29.3.1", "@sinonjs/fake-timers": "^9.1.2", @@ -31262,8 +32636,9 @@ }, "plugins/typescript/node_modules/@jest/globals": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", + "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", "dev": true, - "license": "MIT", "dependencies": { "@jest/environment": "^29.3.1", "@jest/expect": "^29.3.1", @@ -31276,8 +32651,9 @@ }, "plugins/typescript/node_modules/@jest/types": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", + "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", "dev": true, - "license": "MIT", "dependencies": { "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", @@ -31292,24 +32668,27 @@ }, "plugins/typescript/node_modules/@sinonjs/fake-timers": { "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", + "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^1.7.0" } }, "plugins/typescript/node_modules/@types/yargs": { "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.17.tgz", + "integrity": "sha512-72bWxFKTK6uwWJAVT+3rF6Jo6RTojiJ27FQo8Rf60AL+VZbzoVPnMFhKsUnbjR8A3BTCYQ7Mv3hnl8T0A+CX9g==", "dev": true, - "license": "MIT", "dependencies": { "@types/yargs-parser": "*" } }, "plugins/typescript/node_modules/ansi-styles": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "license": "MIT", "engines": { "node": ">=10" }, @@ -31319,16 +32698,18 @@ }, "plugins/typescript/node_modules/ci-info": { "version": "3.7.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", + "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "plugins/typescript/node_modules/jest-message-util": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", + "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.3.1", @@ -31346,8 +32727,9 @@ }, "plugins/typescript/node_modules/jest-mock": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", "dev": true, - "license": "MIT", "dependencies": { "@jest/types": "^29.3.1", "@types/node": "*", @@ -31359,8 +32741,9 @@ }, "plugins/typescript/node_modules/jest-util": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", + "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", "dev": true, - "license": "MIT", "dependencies": { "@jest/types": "^29.3.1", "@types/node": "*", @@ -31375,8 +32758,9 @@ }, "plugins/typescript/node_modules/pretty-format": { "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, - "license": "MIT", "dependencies": { "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", @@ -31388,8 +32772,9 @@ }, "plugins/typescript/node_modules/react-is": { "version": "18.2.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "plugins/typescript/node_modules/typescript": { "version": "4.9.5", @@ -31436,7 +32821,8 @@ }, "plugins/upload-assets-to-s3/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "plugins/webpack": { "name": "@dotcom-tool-kit/webpack", @@ -31536,7 +32922,8 @@ }, "plugins/webpack/node_modules/tslib": { "version": "2.4.1", - "license": "0BSD" + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, "types/financial-times__package-json": { "name": "@types/financial-times__package-json", From 6462d721ce5a2cb559e6a65448ff48a915ba1592 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 14:40:34 +0100 Subject: [PATCH 259/321] ci: release prereleases from next branch --- .circleci/config.yml | 91 +++++++++++++++++++++++--------------- release-please-config.json | 1 + 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index aec6c6fb4..9259b5ff5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,8 +7,7 @@ references: # # Workspace # - container_config_node: - &container_config_node + container_config_node: &container_config_node working_directory: ~/project/build docker: - image: cimg/node:<< parameters.node-version >> @@ -19,16 +18,14 @@ references: workspace_root: &workspace_root ~/project - attach_workspace: - &attach_workspace + attach_workspace: &attach_workspace attach_workspace: at: *workspace_root # # Cache creation # - create_cache: - &create_cache + create_cache: &create_cache save_cache: key: cache-v1-{{ .Branch }}-{{ checksum "./package.json" }} paths: @@ -37,8 +34,7 @@ references: # # Cache restoration # - restore_cache: - &restore_cache + restore_cache: &restore_cache restore_cache: keys: - cache-v1-{{ .Branch }}-{{ checksum "./package.json" }} @@ -46,48 +42,41 @@ references: # # Filters # - filters_only_main: - &filters_only_main + filters_only_main: &filters_only_main branches: only: - main - filters_only_renovate_nori: - &filters_only_renovate_nori + filters_only_renovate_nori: &filters_only_renovate_nori branches: only: /(^renovate-.*|^nori\/.*)/ - filters_ignore_tags_renovate_nori_build_main: - &filters_ignore_tags_renovate_nori_build_main + filters_ignore_tags_renovate_nori_build_main: &filters_ignore_tags_renovate_nori_build_main tags: ignore: /.*/ branches: ignore: /(^renovate-.*|^nori\/.*|^gh-pages|^main$)/ - filters_main_branch: - &filters_main_branch + filters_main_branch: &filters_main_branch branches: only: - main - filters_release_build: - &filters_release_build + filters_release_build: &filters_release_build tags: only: - /^[\w-]+-v\d+\.\d+\.\d+$/ branches: ignore: /.*/ - filters_prerelease_build: - &filters_prerelease_build + filters_prerelease_build: &filters_prerelease_build tags: only: - /^[\w-]+-v\d+\.\d+\.\d+(?:-\w+\.\d+)$/ branches: ignore: /.*/ - filters_orbs_release_build: - &filters_orbs_release_build + filters_orbs_release_build: &filters_orbs_release_build tags: only: # CircleCI doesn't allow prerelease versions to be published @@ -144,6 +133,23 @@ jobs: --repo-url=${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME} --monorepo-tags + release-please-next: + <<: *container_config_node + steps: + - *attach_workspace + - run: + name: Update release-please release PR + command: npx release-please@15 release-pr --token=${RELEASE_PLEASE_GITHUB_TOKEN} + --repo-url=${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME} + + - run: + name: Release any unreleased PR merges + command: npx release-please@15 github-release + --token=${RELEASE_PLEASE_GITHUB_TOKEN} + --repo-url=${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME} + --monorepo-tags + --prerelease + publish: <<: *container_config_node steps: @@ -184,21 +190,21 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - test: requires: - build-v<< matrix.node-version >> name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - lint: requires: - build-v<< matrix.node-version >> name: lint-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] release-please: when: @@ -211,6 +217,19 @@ workflows: filters: <<: *filters_only_main + release-please-next: + when: + not: + equal: + - scheduled_pipeline + - << pipeline.trigger_source >> + jobs: + - release-please: + filters: + branches: + only: + - next + renovate-nori-build-test: when: not: @@ -228,21 +247,21 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - test: requires: - build-v<< matrix.node-version >> name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - lint: requires: - build-v<< matrix.node-version >> name: lint-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] build-test-publish: when: @@ -257,7 +276,7 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - test: filters: <<: *filters_release_build @@ -266,7 +285,7 @@ workflows: name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - lint: filters: <<: *filters_release_build @@ -275,7 +294,7 @@ workflows: name: lint-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - publish: context: npm-publish-token filters: @@ -297,7 +316,7 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - test: filters: <<: *filters_prerelease_build @@ -306,7 +325,7 @@ workflows: name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - lint: filters: <<: *filters_prerelease_build @@ -315,7 +334,7 @@ workflows: name: lint-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - prepublish: context: npm-publish-token filters: @@ -339,7 +358,7 @@ workflows: name: build-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] - test: requires: - build-v<< matrix.node-version >> @@ -347,7 +366,7 @@ workflows: name: test-v<< matrix.node-version >> matrix: parameters: - node-version: [ '18.20', '20.12' ] + node-version: ['18.20', '20.12'] # Prior to producing a development orb (which requires credentials) basic validation, linting, and even unit testing can be performed. # This workflow will run on every commit diff --git a/release-please-config.json b/release-please-config.json index b444ce935..51921988a 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -2,6 +2,7 @@ "bootstrap-sha": "47035e3bd4e3ac399319b3421ce86a82f1c1ab21", "plugins": ["node-workspace"], "prerelease": true, + "versioning": "prerelease", "bump-minor-pre-major": true, "bump-patch-for-minor-pre-major": true, "packages": { From 7d31305efe46d36ed91fabef832340d7ed496d58 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 15:15:42 +0100 Subject: [PATCH 260/321] ci: set release-please target branch to next Co-authored-by: Ivo Murrell --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9259b5ff5..b5df55437 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -141,6 +141,7 @@ jobs: name: Update release-please release PR command: npx release-please@15 release-pr --token=${RELEASE_PLEASE_GITHUB_TOKEN} --repo-url=${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME} + --target-branch next - run: name: Release any unreleased PR merges @@ -149,6 +150,7 @@ jobs: --repo-url=${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME} --monorepo-tags --prerelease + --target-branch next publish: <<: *container_config_node From 741dada3fa41640c6b8b6fa92eac453b7ff65e68 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 15:22:09 +0100 Subject: [PATCH 261/321] ci: run correct release please job on next --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b5df55437..498dcdb18 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -226,7 +226,7 @@ workflows: - scheduled_pipeline - << pipeline.trigger_source >> jobs: - - release-please: + - release-please-next: filters: branches: only: From 135d26f7d72b71496f7451518f0e6f993a5a2242 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 16:09:15 +0100 Subject: [PATCH 262/321] chore: remove FAQ doc it's stuff that's either out of date for `next` or probably better covered elsewhere --- docs/faq.md | 83 ----------------------------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 docs/faq.md diff --git a/docs/faq.md b/docs/faq.md deleted file mode 100644 index b8c33c292..000000000 --- a/docs/faq.md +++ /dev/null @@ -1,83 +0,0 @@ - -# Tool Kit FAQs - -Below are responses to some general questions about Tool Kit that have been asked during migrations. If your question is not answered here please ask in the [#tool-kit](https://app.slack.com/client/T025C95MN/C02TRE2V2Q1/thread/C042NBBTM-1671107986.307219) slack channel and consider adding it, and the answer, to this document. - -## How do I add package specific configuration (for e.g. ESLint) to the Tool Kit plugin (e.g. @dotcom-tool-kit/eslint))? - -As much as possible Tool Kit doesn't handle configuration for third party packages. The purpose of Tool Kit’s plugins for packages is to get them working in the FT development workflow with the minimum possible configuration. Tool Kit plugins will leave package configuration to a specific configuration file for that package (e.g. `.eslintrc` for the ESLint package). - -## How can I use custom commands for my tooling that are not accommodated for by Tool Kit's config? - -You don't need to use Tool Kit for everything. Tool Kit handles common tooling use cases that are required for most apps to work in the Customer Products ecosystem, but it's fine for your app to include additional tooling features that don't use Tool Kit at all. - -See [How do I run watch mode for tests with Tool Kit?](#how-do-i-run-watch-mode-for-tests-with-tool-kit) for a specific example of calling a third party package that Tool Kit configures without using Tool Kit at all. - -## How do I run watch mode for tests with Tool Kit? - -Now that we manage tasks with npm scripts, you can define a script to run your tests in watch mode: - -```json -{ - "scripts": - { - "watch-tests": "jest --watch" - } -} -``` - -Then run `npm run watch-tests` to execute your script. - -You can also use the package directly with npx to run your test runner with any options you wish: - -```sh -npx jest path/to/tests --watch -``` - -Note, this is an example of a script that doesn't use Tool Kit at all, and that's fine. - -## Is there a central list of all hooks and tasks available in Tool Kit? - -Funny you should ask! We have just the thing: - -| Hook | Hook exported by plugin | Possible tasks | -|---------------------|-------------------------|----------------------| -| `run:local` | npm | `Node` | -| | | `Nodemon` | -| | | `NextRouter` | -| | | `WebpackDevelopment` | -| | | `WebpackWatch` | -| | | `TypeScriptWatch` | -| `test:local` | npm | `Mocha` | -| | | `JestLocal` | -| | | `Eslint` | -| | | `CypressLocal` | -| | | `TypeScriptTest` | -| `build:local` | npm | `BabelDevelopment` | -| | | `WebpackDevelopment` | -| | | `TypeScriptBuild` | -| `build:ci` | circleci | `BabelProduction` | -| | | `WebpackProduction` | -| `test:ci` | circleci | `Eslint` | -| | | `Mocha` | -| | | `JestCi` | -| | | `CypressCi` | -| `deploy:review` | circleci-deploy | `HerokuReview` | -| `deploy:staging` | circleci-deploy | `HerokuStaging` | -| `test:review` | circleci-deploy | `NTest` | -| | | `Pa11y` | -| `test:staging` | circleci-deploy | `NTest` | -| `teardown:staging` | circleci-deploy | `HerokuTeardown` | -| `deploy:production` | circleci-deploy | `HerokuProduction` | -| `publish:tag` | circleci-npm | `NpmPublish` | -| `cleanup:remote` | heroku | `NpmPrune` | -| `release:remote` | heroku | `UploadAssetsToS3` | -| `build:remote` | heroku | `BabelProduction` | -| | | `WebpackProduction` | -| `git:precommit` | husky-npm | `LintStaged` | -| `git:commitmsg` | husky-npm | | -| `test:staged` | lint-staged-npm | `Eslint` | -| `format:staged` | lint-staged-npm | `Prettier` | -| `format:local` | prettier | `Prettier` | - -[table updated 4th January 2023] From 61e05e0cda381aed7007acc1a2aa42d8a32e0dc3 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Thu, 25 Apr 2024 16:12:23 +0100 Subject: [PATCH 263/321] chore: remove migrating-to-tool-kit doc no longer relevant, initing a new repo use case is probably better served by other docs --- docs/migrating-to-tool-kit.md | 286 ---------------------------------- 1 file changed, 286 deletions(-) delete mode 100644 docs/migrating-to-tool-kit.md diff --git a/docs/migrating-to-tool-kit.md b/docs/migrating-to-tool-kit.md deleted file mode 100644 index b12ab547c..000000000 --- a/docs/migrating-to-tool-kit.md +++ /dev/null @@ -1,286 +0,0 @@ -# Migrating to Tool Kit from n-gage - -## Introduction - -Tool Kit is our suite of developer tooling for FT.com applications and -components. Tool Kit is designed to handle all parts of your workflow, from -building to testing to deploying. You can read more about the structure and -philosophy of Tool Kit in the [README](../README.md). - -Previously, [n-gage](https://github.com/Financial-Times/n-gage) was the main -tool used in the FT to orchestrate projects, and Tool Kit has been designed as -its replacement. This migration guide focuses on how to migrate from n-gage to -Tool Kit and so will give analogies and guidance based on it. Therefore, this -text is recommended only for projects already using n-gage, though it _may_ help -push you in the right direction if you're creating a fresh, new project. - -## Prerequisites - -Prior to using the migration tool, please make sure you are using npm 7 or above. - -## The Migration Tool - -We have created an interactive tool that will hopefully automate most of the -dull refactoring required to hook up your project with Tool Kit. The tool tries -to be as transparent about what it's doing as possible so should be easy enough -to follow along with. - -The migration tool is published to npm as `@dotcom-tool-kit/create`. Thanks to -some [syntax sugar -magic](https://docs.npmjs.com/cli/v7/commands/npm-init#description) provided by -npm's `npm init` script this means you can run - -```shell -npm init @dotcom-tool-kit@latest -``` - -within your repository to fetch the tool and start migrating. We include the -`@latest` specifier here to make sure you're using the latest version of the -migration tool, as `npx` has a particularly aggressive cache. Answer the -questions posed by the tool's prompts to configure Tool Kit in a way that's -suitable for your app or service. Let's now look in detail at each of the steps -in the migration process. - -## Step-By-Step - -The Tool Kit migration tool will ask you a series of questions about your -project and how much you want to immediately migrate. Let's copy each prompt -here and break down what they mean, why we need it, and what it will do. Note -that you might not see all these prompts in your particular run depending on how -complex the migration is. - -### What Kind Of App? - -``` -What kind of app is ${app}? -- A user-facing (frontend) app -- A service/backend app -``` - -The first question is key! Here you choose what kind of app you're migrating, -which will dictate many of the plugins that will be pulled in. Frontend apps -will use build tools like Webpack to bundle their code for the browser whilst -backend apps and services might use node and npm. These plugins are all bundled -up in a 'compilation' plugin called something like -`@dotcom-tool-kit/frontend-app` whose sole job is to list a set of other plugins -to include. - -### Plugins - -``` -Would you like to install any additional plugins? -- Jest -- Mocha -- ESLint -- Prettier -- lint-staged -``` - -You are then given the opportunity to add various plugins for other tools you -use in your project. It makes sense to choose all the ones you are already -using, but now is also a good chance to try out new tools you've been meaning to -integrate into your stack, such as `dotcom-tool-kit/prettier`! Note: if you don't already have Prettier installed it may be initially a little disruptive with many formatting changes. - -### ESLint Config - -``` -Would you like to add a default eslint config file at ./eslintrc.js? -``` - -Selecting "yes" will generate an `eslintrc.js` file at your project's root directory, which extends the ESLint shared configuration [`@financial-times/eslint-config-next`](https://github.com/Financial-Times/eslint-config-next), and install `@financial-times/eslint-config-next` for you automatically. If you've previously selected `@dotcom-tool-kit/frontend-app` for your app, the generated `.eslintrc.js` file will look like [this](https://github.com/Financial-Times/next-user-facing-app-template/blob/main/.eslintrc.js), whereas if you've selected `@dotcom-tool-kit/backend-heroku-app`, the generated `.eslintrc.js` file will look like [this](https://github.com/Financial-Times/next-service-app-template/blob/main/.eslintrc.js). - -### CircleCI Config - -``` -Would you like a CircleCI config to be generated? This will overwrite the current config at .circleci/config.yml. -``` - -Tool Kit provides a CircleCI orb to call the CI hooks for PRs and deployments. -It's recommended that you delete your old CircleCI config and let Tool Kit -generate a new one for you that will use the Tool Kit orb for all of the -different workflows you'd typically expect in a project. - -If you have a workflow that is a little atypical then you will be free to add those in after the file has been generated (you'll want to make sure you remove the automated header comment at the top of the file so that your changes aren't overwritten in the -future.) Feel free to peruse the [source -code](https://github.com/Financial-Times/dotcom-tool-kit/tree/HEAD/orb/src) and -the -[documentation](https://circleci.com/developer/orbs/orb/financial-times/dotcom-tool-kit) -to see the inner workings of the orb. - -### Deleting n-gage - -``` -Should we uninstall obsolete n-gage and n-heroku-tools packages? -``` - -n-gage and n-heroku-tools have now been replaced by Tool Kit and shouldn't be -required any more, so we suggest you delete them from your `package.json`. - -You may opt to keep them for now if there are some esoteric tasks that -they're handling that Tool Kit doesn't support yet. - -If you're having to do this, please post in the -[#cp-platforms-team](https://financialtimes.slack.com/archives/C3TJ6KXEU) Slack -channel so we can fill in that gap! - -### Confirmation and Installation - -``` -so, we're gonna: - -install the following packages: -- ${package 1} -- ${package 2} - -uninstall the following packages: -- ${package 3} -- ${package 4} - -create a .toolkitrc.yml containing: -${config contents} - -regenerate .circleci/config.yml - -sound good? -``` - -You'll be given an opportunity to review and confirm the changes you're making -before executing them. If you do confirm them then the following will happen -(skipping the steps you've not enabled): - -1. Your `package.json` will be modified with the listed packages - installed/uninstalled -2. `npm install` will be run to update your `node_modules` and - `package-lock.json` (if applicable) with the npm changes -3. The `.toolkitrc.yml` configuration file will be written listing the plugins - you've selected -4. Deleting your old CircleCI configuration file ready to have a new one - regenerated -5. Run `npx dotcom-tool-kit --install`. This command calls an `install` method - that's defined for each hook, which will handle the logic to slot the hook - into the place it's meant to 'hook' into, e.g., installing npm hooks into the - `scripts` property in the `package.json`. (This is also where the CircleCI - config is regenerated to insert the appropriate CI hooks.) - -Sometimes the final step will fail, but this usually indicates that there are -some ambiguities in your configuration that can be clarified in the subsequent steps. - -### Task Conflicts - -``` -Hook ${hook} has multiple tasks configured for it, so an order -must be specified. Please select the 1st package to run. -- ${task 1} -- ${task 2} -- finish -``` - -In some projects you will find multiple tasks are configured to use the same -hook. A common example would be the `@dotcom-tool-kit/eslint` and -`@dotcom-tool-kit/mocha` plugins, which both define tasks that use the -`test:local` hook. - -Tool Kit does not assume the order you want those to run, as -in some cases one of the tasks might depend on the other, so you need to declare -the order explicitly. This is expanded on in its own [documentation -page](./resolving-hook-conflicts.md), but the migration tool takes you through -the process. - -If you don't want some of the tasks to be included in the hook at all, just select the -`finish` option after the rest of the tasks have been selected and the remainder -won't be run. - -### Setting Options - -``` -Please now configure the options for the ${plugin} plugin. -Set a value for '${option}' -``` - -You must set any required options for plugins to continue. The optional ones may be skipped. These options will be added to your `.toolkitrc`. In the future, we will add support for default values in the migration tool (they are already available within Tool Kit -itself,) so that for most cases you could accept default values, even for fields -that are required. - -Some plugins will have specially-made prompts to allow -setting options for more complex scenarios, such as the Heroku plugin which -prompts you to fill in scaling information for each app you have in your -project's Heroku pipeline. - -### Migrating Your Makefile - -``` -We recommend deleting your old Makefile as it will no longer be used. In the -future you can run tasks with 'npm run' instead. Make sure that you won't be -deleting any task logic that hasn't already been migrated to Tool Kit. If you -find anything that can't be handled by Tool Kit then please let the Platforms -team know. - -We've found some targets in your Makefile which could be migrated to Tool Kit: -- Your ${makefile target} target is likely handled by the ${target} hook in Tool Kit - -We don't know if these other Makefile targets can be migrated to Tool Kit. -Please check what they're doing: -- ${makefile target} -- ${makefile target} -``` - -Finally, the tool will give guidance on what the do with the `Makefile` in your -project that was integrated with n-gage. It will try and recommend equivalent -hooks based on the name of the targets within the `Makefile` (the `test:local` -hook for a `test` target, for example,) but sometimes you'll want to leave some -of the targets in at the beginning of the migration and gradually transition -everything over to Tool Kit. Regardless, this step just provides some -suggestions and the migration tool doesn't perform any actions so you'll need to -delete the `Makefile` yourself if you don't think it's needed anymore. - -Remember that – assuming you didn't delete it in the earlier step – some of the `make` -commands come from `n-gage` itself and won't necessarily be in the `Makefile`, -such as `make install`. - -You'll also want to ensure that: - -1. You have configured the same entry point in `.toolkitrc.yml` as in your `Makefile`. This must be set as an option (if it is not the default `server/app.js`). - - eg. - - ``` - nht run --script server/cluster.js - ``` - - in your `Makefile` would become - - ``` - options: - "@dotcom-tool-kit/node": - entry: server/cluster.js - ``` - - in `.toolkitrc.yml` - -2. You have moved any environment variables explicitly set in your `Makefile` to the appropriate rc file, eg. `.mocharc.js` for mocha unit tests - -## Migrating Your Heroku Pipeline - -The migration tool cannot automate reconfiguring your Heroku -pipeline to integrate with Tool Kit. You will need to ensure that: - -- Your pipeline is connected to the project's GitHub repository -- PRs create review apps -- Commits to main can be deployed from a staging app - -This might be how your pipeline was already configured, but you should check to make sure that -automatic deployments are still working. Try reconnecting to GitHub if they -are not. - -A step-by-step guide with screenshots can be found -[here](https://docs.google.com/document/d/1b7WlRfhiWlbDsSSGP3TllYaGMJbx9nCdAtcr8_OWEWM). - -## To conclude - -To ensure the migration has succeeded, you can run the following commands locally: - -`npm run build` \ -`npm start` \ -`npm test` - -On pull request, you can check that CI jobs are running as expected. From d3b49a2ce4500249184c23c69e9f2640b0ba5d05 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 08:33:53 +0100 Subject: [PATCH 264/321] docs: rework custom plugins doc into "extending tool kit" explaining ad hoc task and hook config --- docs/custom-plugins.md | 142 ------------------------------------- docs/extending-tool-kit.md | 136 +++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 142 deletions(-) delete mode 100644 docs/custom-plugins.md create mode 100644 docs/extending-tool-kit.md diff --git a/docs/custom-plugins.md b/docs/custom-plugins.md deleted file mode 100644 index 6ab9f3c2c..000000000 --- a/docs/custom-plugins.md +++ /dev/null @@ -1,142 +0,0 @@ -# Creating a custom Tool Kit plugin - -If your app requires some tooling that's not part of Tool Kit, you can write a custom plugin for that feature, which can work seamlessly together with the core Tool Kit plugins. This is the **only supported way** of using tooling that Tool Kit doesn't currently include. - -If you're looking to implement tooling in your repository that would require things like custom `npm` scripts, Bash scripts, or editing the Tool Kit-managed CircleCI config, **you should be writing a custom plugin**. - -A custom plugin can be written for a single repo or distributed as an npm package to be consumed by multiple repos owned by your team. The custom plugins themselves will be maintained and supported **by your team**, not Platforms. - -If there's wide demand for a particular custom plugin (for example, if it starts being used across multiple teams), we will consider adopting that plugin into Tool Kit. Writing a custom plugin (rather than implementing the tooling another way) will make it much more likely for us to be able to add the feature to Tool Kit. - -## Common plugin structure - -We recommend creating a `toolkit` folder at the root of your repository to contain your custom plugins, and folders inside that for each plugin. Each plugin folder should contain at least **an empty `.toolkitrc.yml` file** and **an empty `index.js`**. - -Let's say you're creating a plugin to run [Rollup](https://rollupjs.org). Your folder structure should look like this: - -``` -└ toolkit - └ rollup - ├ .toolkitrc.yml - └ index.js -``` - -This plugin can then be included in your top-level `.toolkitrc.yml` by referencing it as a relative path: - -```yml -plugins: - - './toolkit/rollup' -``` - -## Creating a task to be run by an existing hook - -Consider the tooling you're implementing, and when you'd expect it to run. Tool Kit likely already has the hooks included for those scenarios, so have a look at the core plugins to see if there's something similar, and look at what hooks it runs on by default in its `.toolkitrc.yml`. - -For something like Rollup, you'd probably expect it to run for local development, on continuous integration builds so you can run your tests, and when building an app so it can run in review or production. Tool Kit has a [built-in Webpack](https://github.com/Financial-Times/dotcom-tool-kit/tree/main/plugins/webpack) plugin; since it's also a bundler, like Rollup, it's a good example to compare to for your custom plugin. - -The Webpack plugin [runs by default](https://github.com/Financial-Times/dotcom-tool-kit/blob/main/plugins/webpack/.toolkitrc.yml) on the `build:local`, `build:ci`, and `build:remote` hooks, which sound like exactly the hooks you're looking for. - -To get Rollup to run at these points, you'll need to create a subclass of the `Task` class from `@dotcom-tool-kit/types`, implement the `run` method, and export it in an array of `tasks`. Your `toolkit/rollup/index.js` might look like this: - -```js -const { Task } = require('@dotcom-tool-kit/types') -const rollup = require('rollup') -const loadConfigFile = require('rollup/dist/loadConfigFile') -const path = require('path') - -class Rollup extends Task { - async run() { - const config = path.join(process.cwd(), 'rollup.config.js') - const { options, warnings } = await loadConfigFile(config) - - // print any config warnings to the console - warnings.flush() - - for (const optionsEntry of options) { - const bundle = await rollup.rollup(optionsEntry) - await Promise.all(optionsEntry.output.map(bundle.write)) - } - } -} - -exports.tasks = [Rollup] -``` - -Then, in the plugin's `.toolkitrc.yml`, list this task as the default task to run on the hooks you need: - -```yml -hooks: - 'build:local': Rollup - 'build:ci': Rollup - 'build:remote: Rollup -``` - -You should install `@dotcom-tool-kit/types` and the tooling you're implementing as `devDependencies` of your repo (e.g. `npm install --save-dev @dotcom-tool-kit/types rollup`). - -## Implementing a new hook - -A Hook defines an abstract label to run tasks with, as well as managing where in other project configuration it's run from. For example, the built-in `circleci` plugin defines a `build:ci` hook, which lets tasks like Rollup run in CI, and it specifies that `build:ci` should be run by a CircleCI job and automatically manages the configuration in `.circleci/config.yml` to run that job. - -This abstraction lets us write different plugins for defining tasks to be run, separate from the plugins defining where they should be run from, whilst maintaining the link between them. We've already seen that `build:ci` could be running Rollup, or Webpack, or any other task; in addition, `build:ci` itself could be defined by a different plugin, such as a Github Actions plugin, that would automatically manage configuration in `.github/workflows`. - -The automatic configuration management is implemented by `Hook` subclasses. These define an `isInstalled` method that should return `true` if the hook is correctly installed in the repository or `false` if it needs installing, and an `install` method to actually perform the installation. Every time Tool Kit runs, it checks that every hook is installed in your repo, and if any aren't, it exits with an error (to ensure the repo is always consistent with what it expects). You can then run `dotcom-tool-kit --install` to run the installation of every hook that isn't installed. - -If you find yourself asking a question like "how do I run a Tool Kit task from a different npm script", **you should implement a hook** to allow Tool Kit to automatically manage that configuration for any new repos using your plugin, rather than expecting new users to add that configuration themselves when installing the plugin. - -Hooks have a loose naming convention of `category:environment`. This is only meant for humans to be able to intuitively understand which hooks are related; it's not required by the Tool Kit core itself. - -Let's say you want to run some task on the npm `prepare` script (which automatically runs after `npm install` and before `npm publish`). We'll call that hook `prepare:local`, and the plugin will live in `toolkit/npm-prepare` ([structured as above](#common-plugin-structure)). Create a subclass of the `Hook` class from `@dotcom-tool-kit/types`, implement the `isInstalled` and `install` methods, and export a `hooks` object to map it to the name we're giving it. Your `toolkit/npm-prepare/index.js` might include: - -```js -const { Hook } = require('@dotcom-tool-kit/types') -const loadPackageJson = require('@financial-times/package-json') - -class PrepareHook extends Hook { - get packageJson() { - if (!this._packageJson) { - const filepath = path.resolve(process.cwd(), 'package.json') - this._packageJson = loadPackageJson({ filepath }) - } - - return this._packageJson - } - - async isInstalled() { - return this.packageJson.getField('scripts')?.prepare === 'dotcom-tool-kit prepare:local' - } - - async install() { - this.packageJson.requireScript({ - stage: 'prepare', - command: 'dotcom-tool-kit prepare:local' - }) - - this.packageJson.writeChanges() - } -} - -export const hooks = { - 'prepare:local': PrepareHook -} -``` - -There are a handful of common base classes that Tool Kit includes for common hook usecases (such as CircleCI configuration or npm `package.json` scripts) that you can use, instead of implementing your hook completely from scratch. For example, we can build our `prepare:local` hook on top of the `PackageJsonScriptHook` built-in class: - -```js -const { PackageJsonScriptHook } = require('@dotcom-tool-kit/package-json-hook') - -class PrepareHook extends PackageJsonScriptHook { - key = 'prepare' - hook = 'prepare:local' -} -``` - -After you've implemented your hook, running `dotcom-tool-kit --install` will add a `prepare` script to your `package.json`. - -## Summary - -- You can create new custom **tasks** to run tooling that Tool Kit doesn't support yet -- You can create custom **hooks** to run Tool Kit tasks in new scenarios -- Please [talk to the Platforms team](https://financialtimes.slack.com/archives/C02TRE2V2Q1) if you need help writing a custom plugin, want to discuss your use case, or to propose new features you think might be useful across multiple repositories & teams - -✌️ diff --git a/docs/extending-tool-kit.md b/docs/extending-tool-kit.md new file mode 100644 index 000000000..b4f7b3b07 --- /dev/null +++ b/docs/extending-tool-kit.md @@ -0,0 +1,136 @@ +# Extending Tool Kit + +Tool Kit provides a development workflow for tooling that's common to most Customer Products projects. But almost every project has unique requirements that the default set of plugins and configuration in Tool Kit doesn't cover. For these use cases, there are various ways you can extend Tool Kit. + +You don't have to use Tool Kit for every tooling use case in your project. However, using Tool Kit for your custom tooling makes it more likely that it will be shareable between multiple projects and teams and potentially adopted into Tool Kit itself. + +## Running existing Tool Kit tasks in new scenarios + +In your repo's `.toolkitrc.yml`, you can define new commands to run tasks: + +```yml +commands: + build:e2e: Webpack +``` + +This can be run with `npx dotcom-tool-kit build:e2e`. + +A task's options can be set on a per-command basis, allowing the same task to be used for multiple use cases: + +```yml +commands: + build:local: + Webpack: + configFile: webpack.config.js + build:e2e: + Webpack: + configFile: webpack.e2e.config.js +``` + +Tool Kit **hooks** manage files like `package.json` and `.circleci/config.yml` to run commands from your existing tooling like npm scripts and CircleCI jobs. Hooks can be configured in your `.toolkitrc.yml` to integrate your new commands: + +```yml +options: + hooks: + - PackageJson: + scripts: + e2e: build:e2e + - CircleCIConfig: + jobs: + - name: build-e2e + command: build:e2e + workflows: + - name: 'tool-kit' + jobs: + - name: build-e2e + requires: + - setup +``` + +Adding this configuration and running `npx dotcom-tool-kit --install` will install the new npm script and CircleCI job into your repo, alongside the existing configuration from your Tool Kit plugins. + +## Creating a custom Tool Kit plugin + +If your app requires some tooling that's not provided by a first-party Tool Kit plugin, you can write a custom plugin for that feature, which works seamlessly together with the core Tool Kit plugins. + +A custom plugin can be written for a single repo or distributed as an npm package to be consumed by multiple repos owned by your team. The custom plugins themselves will be maintained and supported **by your team**, not Platforms, although we can . + +If there's wide demand for a particular custom plugin (for example, if it starts being used across multiple teams), we will consider adopting that plugin into Tool Kit. Writing a custom plugin (rather than implementing the tooling another way) will make it much more likely for us to be able to add the feature to Tool Kit. + +### Common plugin structure + +We recommend creating a `tool-kit` folder at the root of your repository to contain your custom plugins, and folders inside that for each plugin. Each plugin folder must contain at least a `.toolkitrc.yml` file. + +The `.toolkitrc.yml` is the manifest that tells the Tool Kit plugin loader what your plugin needs to load. It must contain a `version` field (Tool Kit will currently only load a version `2` plugin), and for custom plugins will probably need a `tasks` field telling Tool Kit to load your custom tasks. + +Let's say you're creating a plugin to run [Rollup](https://rollupjs.org). Your folder structure should look like this: + +``` +└ tool-kit + └ rollup + ├ .toolkitrc.yml + └ tasks + └ rollup.js +``` + +The `.toolkitrc.yml` would then contain: + +```yml +version: 2 + +tasks: + Rollup: ./tasks/rollup.js +``` + +This plugin can then be included in your top-level `.toolkitrc.yml` by referencing it as a relative path: + +```yml +plugins: + - './tool-kit/rollup' +``` + +### Writing the task + +Create a subclass of the `Task` class from `@dotcom-tool-kit/base`, implement the `run` method, and export it as the default export of the task module. + +You'll need to install `@dotcom-tool-kit/base` and the tooling you're implementing as `devDependencies` of your repo (e.g. `npm install --save-dev @dotcom-tool-kit/base rollup`). + +Your `tool-kit/rollup/index.js` might look like this: + +```js +const { Task } = require('@dotcom-tool-kit/base') +const rollup = require('rollup') +const loadConfigFile = require('rollup/dist/loadConfigFile') +const path = require('path') + +class Rollup extends Task { + async run() { + const config = path.join(process.cwd(), 'rollup.config.js') + const { options, warnings } = await loadConfigFile(config) + + // print any config warnings to the console + warnings.flush() + + for (const optionsEntry of options) { + const bundle = await rollup.rollup(optionsEntry) + await Promise.all(optionsEntry.output.map(bundle.write)) + } + } +} + +module.exports = Rollup +``` + +Then, in the plugin's `.toolkitrc.yml`, you can provide the default commands this task will run on. It's preferable to do this in the plugin `.toolkitrc.yml` instead of your top-level `.toolkitrc.yml` so your plugin is self-contained and can be more easily moved into its own repo or Tool Kit itself, if it's something that can be shared between multiple repos/teams. + +```yml +version: 2 + +tasks: + Rollup: ./tasks/rollup.js + +commands: + 'build:local': Rollup + 'build:ci': Rollup + 'build:remote': Rollup +``` From 4c6f1570bd02bc1b29f202cbbe3809a65774886e Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 12:24:36 +0100 Subject: [PATCH 265/321] docs: add section on plugin loading to "developing tool kit" --- docs/developing-tool-kit.md | 52 +++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/docs/developing-tool-kit.md b/docs/developing-tool-kit.md index d3e12d2ab..1d97ad475 100644 --- a/docs/developing-tool-kit.md +++ b/docs/developing-tool-kit.md @@ -22,6 +22,53 @@ The script will create the plugin folder and add all the necessary configuration At the root of the repository, `npm run watch` will run the Typescript compiler and build files when you change them. It's recommended to leave that running while you develop things. +## How Tool Kit loads plugins + +The Tool Kit CLI works by recursively loading plugins, merging them, depth-first, into a single [`config` object](../lib/config/src/index.ts), while labelling any conflicts between plugins, and allowing their parent plugins to potentially resolve conflicts. + +As far as the CLI is concerned, a "plugin" is anything with a `.toolkitrc.yml`. This means a user's repo is considered a plugin, which we label `app root` in the config. It's loaded as the first plugin, and all other plugins are loaded as its descendents. + +The Tool Kit CLI initialises in two phases: **loading** plugins, then **resolving** them. + +When **loading** a plugin, we parse its `.toolkitrc.yml`, builds a [`plugin` object](../lib/plugin/src/index.ts), and with the `plugins` array from the `.toolkitrc.yml`, load its children. + +When **resolving** a plugin, first we resolve its children (i.e. depth-first recursion). Then we merge its tasks, hooks, commands, plugin options, task options, and init functions (in that order) into the `config`. + +These all have slightly different logic for what's considered a "conflict", but in general, if a plugin tries to store something with a particular name in the config, and it's already been stored by something that isn't a descendent of this plugin, that's a conflict. + +On the other hand, if there's already a conflict in the config that _did_ come from a descendent of the current plugin, this plugin will replace the conflict with what it's currently trying to store, allowing parents to override their children to resolve conflicts. + +For an example, consider this (simplified) dependency tree of plugins: + +``` +└ app root + └ frontend-app + ├ backend-heroku-app + │ ├ circleci + │ └ heroku + └ webpack +``` + +The plugins will be loaded in this order: + +1. `app root` +2. `frontend-app` +3. `backend-heroku-app` +4. `circleci` +5. `heroku` +6. `webpack` + +And then resolved in this order: + +1. `circleci` +2. `heroku` +3. `backend-heroku-app` +4. `webpack` +5. `frontend-app` +6. `app root` + +This depth-first resolution together with the `app root` being the ultimate ancestor plugin means a repo's `.toolkitrc.yml` can override anything (including conflicts) from any plugin, allowing users to have the final say over what's running when and how it's configured. + ## Plugin structure Tool Kit plugins are Node modules. Any code in the entry point of the plugin will be run when Tool Kit starts up and loads the plugin. You can use this for any initialisation the plugin needs to do, e.g. writing [state](#state) based on the environment. The module can export an array of [tasks](#tasks) and an object of [hooks](#hooks). @@ -36,8 +83,6 @@ A task extends the class `Task` from `@dotcom-tool-kit/types`, implementing its import { Task } from '@dotcom-tool-kit/types' export default class Webpack extends Task { - static description = 'bundle your code with webpack' - async run(): Promise { // call third-party tooling } @@ -157,6 +202,9 @@ Look at the [`state` package](../lib/state/) to see how to define, read and writ ## General philosophy +> [!TIP] +> See also the higher-level [Tool Kit principles](./tool-kit-principles.md). + - The Tool Kit core (`cli/core` and the packages it depends on) should **never** depend on any particular plugin. This would prevent users from using alternatives to that plugin. If you find yourself needing to add something to the core for a particular plugin, think about how other plugins would work with it, and make sure what you're writing is general enough for any similar plugin to work with it. From 298bdbc8e22d0fb0bddcb68de11d1f45ae161972 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Fri, 26 Apr 2024 12:25:08 +0100 Subject: [PATCH 266/321] chore: rename "resolving hook conflicts" to "resolving plugin conflicts" --- ...ng-hook-conflicts.md => resolving-plugin-conflicts.md} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename docs/{resolving-hook-conflicts.md => resolving-plugin-conflicts.md} (94%) diff --git a/docs/resolving-hook-conflicts.md b/docs/resolving-plugin-conflicts.md similarity index 94% rename from docs/resolving-hook-conflicts.md rename to docs/resolving-plugin-conflicts.md index 42bf1f278..f551dc83d 100644 --- a/docs/resolving-hook-conflicts.md +++ b/docs/resolving-plugin-conflicts.md @@ -1,4 +1,4 @@ -# Hooks conflicts +# Tool Kit plugin conflicts Tool Kit allows its plugins, and apps using it, to [configure tasks to run on hooks](../readme.md#hooks). It's possible for this configuration to conflict between plugins, in which case you'll need to resolve the conflict. @@ -24,7 +24,7 @@ For example, if your app requires Webpack to run for `build:local` hooks, but no ```yaml hooks: - 'build:local': WebpackDevelopment + 'build:local': Webpack ``` You can list an array of tasks, which will be run in sequence. For example to run Webpack _then_ Babel: @@ -32,8 +32,8 @@ You can list an array of tasks, which will be run in sequence. For example to ru ```yaml hooks: 'build:local': - - WebpackDevelopment - - BabelDevelopment + - Webpack + - Babel ``` Resolving the conflict isn't an arbitrary choice; it's entirely down to what your app requires, so make sure the resolution covers your usecases. For many standard usecases, there will be a plugin that includes a common set of plugins and hook resolutions for them. Installing a usecase plugin would let the plugin take care of resolution, so you won't need to do it manually in your app. From d76dc39d697da8ed27b12e00db88d0b72d211e58 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 29 Apr 2024 11:21:03 +0100 Subject: [PATCH 267/321] docs: update resolving plugin conflicts --- docs/resolving-plugin-conflicts.md | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/resolving-plugin-conflicts.md b/docs/resolving-plugin-conflicts.md index f551dc83d..4609b351a 100644 --- a/docs/resolving-plugin-conflicts.md +++ b/docs/resolving-plugin-conflicts.md @@ -1,39 +1,47 @@ # Tool Kit plugin conflicts -Tool Kit allows its plugins, and apps using it, to [configure tasks to run on hooks](../readme.md#hooks). It's possible for this configuration to conflict between plugins, in which case you'll need to resolve the conflict. +When two Tool Kit plugins try to configure the same thing, that's a conflict that needs to be resolved. Anything a plugin configures in its `.toolkitrc.yml` can be a conflict. That includes things like which commands are running which hooks and options for tasks, hooks & plugins. -## What causes conflicts? +## Example of a plugin conflict -If you have Tool Kit plugins installed that configure different tasks to run on the same hook, that's a conflict. For example, both the `webpack` and `babel` plugins configure tasks to run on `build:*` hooks. When this happens, you'll get an error that looks like this: +Both the `webpack` and `babel` plugins configure tasks to run on the `build:*` commands. If you install both of them in your app, you'll get an error that looks like this: ``` -These hooks are configured to run different tasks by multiple plugins: +These commands are configured to run different tasks by multiple plugins: build:local: -- WebpackDevelopment by plugin @dotcom-tool-kit/webpack -- BabelDevelopment by plugin @dotcom-tool-kit/babel +- Webpack by plugin @dotcom-tool-kit/webpack +- Babel by plugin @dotcom-tool-kit/babel ``` You might not be using the conflicting plugins directly; they might be installed as dependencies of other plugins you're using. ## Resolving conflicts -The [Tool Kit configuration](../readme.md#configuration) in your app will override any configuration from plugins, which is where default hook tasks are defined. You can provide configuration in your `.toolkitrc.yml` or `package.json` `toolkit` field to specify which of the conflicting Tool Kit tasks you want to run. +The [Tool Kit configuration](../readme.md#configuration) in your repo will override any configuration from plugins, which is treated as a default. You can provide configuration in your `.toolkitrc.yml` to specify which of the conflicting Tool Kit tasks you want to run. For example, if your app requires Webpack to run for `build:local` hooks, but not Babel: ```yaml -hooks: +commands: 'build:local': Webpack ``` -You can list an array of tasks, which will be run in sequence. For example to run Webpack _then_ Babel: +You can also list an array of tasks, which will be run in sequence. For example to run Webpack _then_ Babel: ```yaml -hooks: +commands: 'build:local': - Webpack - Babel ``` +Conflicts between options in plugins are handled in the same way, by providing an override in your `.toolkitrc.yml`. Note that this is a full override; options from plugins aren't merged with your repo's configuration, so you'll need to provide the full set of options for a plugin or task if you're overriding them. + Resolving the conflict isn't an arbitrary choice; it's entirely down to what your app requires, so make sure the resolution covers your usecases. For many standard usecases, there will be a plugin that includes a common set of plugins and hook resolutions for them. Installing a usecase plugin would let the plugin take care of resolution, so you won't need to do it manually in your app. + +## How conflicts are handled internally + +Tool Kit loads plugins as a tree structure. When a plugin loads other plugins, we call those its **children**, and it their **parent**. The children are **sibling** plugins to each other. Tool Kit also considers your repo a plugin; it's the ultimate ancestor of all the other plugins loaded. + +Conflicts only occur between sibling or nibling (child plugins of a sibling) plugins. When children plugins conflict, their parent plugin can override the conflicting configuration to resolve the conflict. If the conflict is left unresloved, it bubbles up through all the parent plugins in this branch of the plugin tree, giving them all an opportunity to resolve it. If the conflict is never resolved by any parent plugins (including your repo), Tool Kit will exit with an error explaining the conflict and which plugins caused it. From 8b26b185a8fcaf22f21886de2507c3fd9e877f7c Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 29 Apr 2024 14:27:15 +0100 Subject: [PATCH 268/321] docs: update and simplify main readme, moving more detailed things to other files --- contributing.md | 15 +++++++ docs/concepts.md | 71 ++++++++++++++++++++++++++++++ readme.md | 111 +++++++++++++++++------------------------------ 3 files changed, 127 insertions(+), 70 deletions(-) create mode 100644 contributing.md create mode 100644 docs/concepts.md diff --git a/contributing.md b/contributing.md new file mode 100644 index 000000000..6548b011e --- /dev/null +++ b/contributing.md @@ -0,0 +1,15 @@ +# Contributing + +Tool Kit is organised as a monorepo with all the different plugins and libraries stored in a single repository. This allows us to quickly investigate and make changes across the whole codebase, as well as making installation easier by sharing dependencies. See the [developer documentation](./docs/developing-tool-kit.md) for a full explanation of the internal architecture of Tool Kit. + +Release versions are not kept in sync between the packages, as we do not want to have to a major version bump for every package whenever we release a breaking change for a single package. + +We use [release-please](https://github.com/googleapis/release-please) to manage releases and versioning. Every time we make a merge to main, release-please checks which packages have been changed, and creates a PR to make new releases for them. It uses the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard to determine whether updates require a patch, minor, or major version bump, and we use [commitlint](https://commitlint.js.org) to enforce the standard in all of our commits. + +This means you should make an effort to think carefully about whether the changes you're making are a new feature or bug fix, and whether they contain any breaking changes. This might seem burdensome at first but it's good practice to make sure you can predict whether other teams' builds are going to break because of your code changes! If your commit will only affect a single package then please also include the name of the package (without the `@dotcom-tool-kit` namespace) in the scope of your commit message, as this makes it easier to see where changes are being made just by a quick glance at the git log. For example, a commit message for a new feature for the `circleci` plugin might look like: + +``` +feat(circleci): add support for nightly workflows +``` + +Note that new plugins should be created with a version number of `0.1.0`. This indicates that the package is still in the early stages of development and could be subject to many breaking changes before it's stabilised. Committing breaking changes whilst your package is `<1.0.0` are treated as minor bumps (`0.2.0`) and both new features and bug fixes as patch bumps (`0.1.1`.) When you're ready, you can release a 1.0 of your plugin by including `Release-As: 1.0.0` in the body of the release commit. diff --git a/docs/concepts.md b/docs/concepts.md new file mode 100644 index 000000000..f21dd49de --- /dev/null +++ b/docs/concepts.md @@ -0,0 +1,71 @@ +## How Tool Kit works + +### Plugins + + + +Tool Kit is a fully modular set of developer tooling. Not every project requires the same tooling, so to make sure different projects only have to install and configure what they need, Tool Kit is made up of several **plugins** that you can install separately to provide different groups of functionality, like [the `npm` plugin](plugins/npm), which lets Tool Kit manage things like `package.json` scripts. + +This means a project that uses Jest for its tests can install [the `jest` plugin](plugins/jest), and a project using Mocha can install [the `mocha` plugin](plugins/mocha), and be able to run them consistently anywhere they're needed, e.g. the `npm run test` script, without having to configure that manually. Plugins can depend on other plugins, so we also publish plugins like [`frontend-app`](./plugins/frontend-app/) that bundle up most of the tooling you'll need into a single package. + +And if there's something you want to use in your repo that's not yet supported by Tool Kit, you can write a [custom plugin](docs/custom-plugins.md) so it can work consistently with any officially-supported tooling. + +Plugins provide **tasks**, which provide the code for running external tooling, and **hooks**, which manage configuration files in your repo that will be running tooling. + +### Tasks + +A **task** is a lightweight abstraction for running some tooling from outside of Tool Kit. Tasks are written in TypeScript, so we can make use of modern Javascript-based tooling and libraries, easily provide structured logging and actionable error messages, and debug them more easily than things like Bash scripts. + +An example of a task is `JestLocal` from the `jest` plugin, which abstracts running Jest tests in a local development environment. Some tasks support [configuration](#configuration). This doesn't replace any native configuration that tooling might have (like a `jest.config.js`). + +### Hooks + + + +## How Tool Kit works + +### Plugins + + + +Tool Kit is a fully modular set of developer tooling. Not every project requires the same tooling, so to make sure different projects only have to install and configure what they need, Tool Kit is made up of several **plugins** that you can install separately to provide different groups of functionality, like [the `npm` plugin](plugins/npm), which lets Tool Kit manage things like `package.json` scripts. + +This means a project that uses Jest for its tests can install [the `jest` plugin](plugins/jest), and a project using Mocha can install [the `mocha` plugin](plugins/mocha), and be able to run them consistently anywhere they're needed, e.g. the `npm run test` script, without having to configure that manually. Plugins can depend on other plugins, so we also publish plugins like [`frontend-app`](./plugins/frontend-app/) that bundle up most of the tooling you'll need into a single package. + +And if there's something you want to use in your repo that's not yet supported by Tool Kit, you can write a [custom plugin](docs/custom-plugins.md) so it can work consistently with any officially-supported tooling. + +Plugins provide **tasks**, which provide the code for running external tooling, and **hooks**, which manage configuration files in your repo that will be running tooling. + +### Tasks + +A **task** is a lightweight abstraction for running some tooling from outside of Tool Kit. Tasks are written in TypeScript, so we can make use of modern Javascript-based tooling and libraries, easily provide structured logging and actionable error messages, and debug them more easily than things like Bash scripts. + +An example of a task is `JestLocal` from the `jest` plugin, which abstracts running Jest tests in a local development environment. Some tasks support [configuration](#configuration). This doesn't replace any native configuration that tooling might have (like a `jest.config.js`). + +### Hooks + + + +A **hook** is the glue between configuration in your repo that will be running Tool Kit and the tasks themselves. Things like scripts in `package.json` or jobs in your CircleCI config can be automatically managed and kept consistent by hooks. + +For example, the `test:local` hook in the `npm` plugin ensures the `test` script is defined in `package.json` to run `dotcom-tool-kit test:local`, then any tasks that are configured to run on `test:local` will be run when you run `npm run test`. + +Plugins can set a default hook for their tasks to run on; for example, the `JestLocal` task [runs by default on the `test:local` hook](./plugins/jest/.toolkitrc.yml#L2). If you've got multiple tasks trying to run on the same hook by default, you'll need to [configure which you want to run](./docs/resolving-hook-conflicts.md). + + + +Hooks are there to be **installed** in your repository. Hook classes contain an `install` method that updates the relevant configuration files to run that hook. This `install` method is called when you run `npx dotcom-tool-kit --install`. This lets Tool Kit plugins automatically manage files like `package.json` or `.circleci/config.yml`. Any changes made by hook installation should be committed. + +When Tool Kit starts up, it checks whether the hooks in your plugins are correctly installed, and will print an error if they're not. This prevents repos from getting out of sync with what Tool Kit expects, ensuring repos are fully consistent and controlled by Tool Kit plugins. + +A **hook** is the glue between configuration in your repo that will be running Tool Kit and the tasks themselves. Things like scripts in `package.json` or jobs in your CircleCI config can be automatically managed and kept consistent by hooks. + +For example, the `test:local` hook in the `npm` plugin ensures the `test` script is defined in `package.json` to run `dotcom-tool-kit test:local`, then any tasks that are configured to run on `test:local` will be run when you run `npm run test`. + +Plugins can set a default hook for their tasks to run on; for example, the `JestLocal` task [runs by default on the `test:local` hook](./plugins/jest/.toolkitrc.yml#L2). If you've got multiple tasks trying to run on the same hook by default, you'll need to [configure which you want to run](./docs/resolving-hook-conflicts.md). + + + +Hooks are there to be **installed** in your repository. Hook classes contain an `install` method that updates the relevant configuration files to run that hook. This `install` method is called when you run `npx dotcom-tool-kit --install`. This lets Tool Kit plugins automatically manage files like `package.json` or `.circleci/config.yml`. Any changes made by hook installation should be committed. + +When Tool Kit starts up, it checks whether the hooks in your plugins are correctly installed, and will print an error if they're not. This prevents repos from getting out of sync with what Tool Kit expects, ensuring repos are fully consistent and controlled by Tool Kit plugins. diff --git a/readme.md b/readme.md index 0c80d8b30..e458d2ab3 100644 --- a/readme.md +++ b/readme.md @@ -6,15 +6,11 @@ Tool Kit is modern developer tooling for FT.com repositories. It's fully modular, allowing repos that need different tooling to install separate plugins that work consistently together. -Tool Kit has been created to enable the FT.com development workflow and only handles common tooling use cases that are required for most apps to work. Tool Kit sets up the minimal configuration for third party packages to run. +Tool Kit only handles common tooling use cases that are required for most apps to work. Tool Kit sets up the minimal configuration for third party packages to run. -Your application does not need to use Tool Kit for all of its tooling and tooling not supported by Tool Kit can be configured directly in your application. +Your repo does not need to use Tool Kit for all of its tooling, and tooling not supported by Tool Kit can be configured directly in your repo. -Tool Kit follows a set of [principles](./docs/tool-kit-principles.md) that guide its development. - -## Installing and using Tool Kit - -For general questions about using Tool Kit please see the [Tool Kit FAQs](./docs/faq.md). +## Installing Tool Kit ### Interactive installation & migration @@ -26,8 +22,12 @@ npm init @dotcom-tool-kit@latest See [the migration guide](./docs/migrating-to-tool-kit.md) for a full explanation of what this script does. +
+ ### Installing and configuring manually + + Install the core of Tool Kit as a `devDependency`: ```sh @@ -48,21 +48,15 @@ plugins: - '@dotcom-tool-kit/jest' ``` -Every time you change your `.toolkitrc.yml`, e.g. adding or removing a plugin, you should tell Tool Kit to install configuration files in your repository: +Every time you change your `.toolkitrc.yml`, e.g. adding or removing a plugin or [configuring](#configuring-tool-kit) a hook, you should tell Tool Kit to install configuration files in your repository: ```sh npx dotcom-tool-kit --install ``` -### Updating existing Tool Kit configuration - -If your project already has a `.toolkitrc.yml` file you can add a new plugin to it by following the steps in the README for that plugin. - -At any time you can run `npx dotcom-tool-kit --help` to review the full list of hooks and tasks configured in your project. - -You can see the list of all available hooks and tasks provided by Tool Kit in the FAQs. +
-### Running Tool Kit +## Running Tool Kit You don't run Tool Kit directly; you run plugin tasks using things like npm scripts, automatically configured in your `package.json` by Tool Kit. With the `npm` and `jest` plugins installed, Jest tests are run with the npm `test` script: @@ -76,45 +70,18 @@ At any time, you can run `--help` to see what plugins you have installed, what c npx dotcom-tool-kit --help ``` -## How Tool Kit works - -### Plugins - - - -Tool Kit is a fully modular set of developer tooling. Not every project requires the same tooling, so to make sure different projects only have to install and configure what they need, Tool Kit is made up of several **plugins** that you can install separately to provide different groups of functionality, like [the `npm` plugin](plugins/npm), which lets Tool Kit manage things like `package.json` scripts. - -This means a project that uses Jest for its tests can install [the `jest` plugin](plugins/jest), and a project using Mocha can install [the `mocha` plugin](plugins/mocha), and be able to run them consistently anywhere they're needed, e.g. the `npm run test` script. Plugins can depend on other plugins, so we can also publish plugins like `frontend-app` that bundle up most of the tooling you'll need into a single package. - -And if there's something you want to use in your repo that's not yet supported by Tool Kit, you can write a [custom plugin](docs/custom-plugins.md) so it can work consistently with any officially-supported tooling. - -Plugins provide **tasks**, which provide the code for running external tooling, and **hooks**, which manage configuration files in your repo that will be running tooling. - -### Tasks +## Core concepts -A **task** is a lightweight abstraction for running some tooling from outside of Tool Kit. Tasks are written in TypeScript, so we can make use of modern Javascript-based tooling and libraries, easily provide structured logging and actionable error messages, and debug them more easily than things like Bash scripts. +- Integration with tooling is grouped into modular **Plugins** that are installed separately. +- Tool Kit abstracts running other tooling with **Tasks**, written in Typescript. +- When running Tool Kit, you run **Commands**, which you (or a plugin) configure to run one or more Tasks. +- **Hooks** manage configuration files in your repository to run Commands from tooling such as npm scripts or CircleCI jobs. -An example of a task is `JestLocal` from the `jest` plugin, which abstracts running Jest tests in a local development environment. Some tasks support [configuration](#configuration). This doesn't replace any native configuration that tooling might have (like a `jest.config.js`). +The [concepts](./docs/concepts.md) document has more details about how these work together. -### Hooks +## Configuring Tool Kit - - -A **hook** is the glue between configuration in your repo that will be running Tool Kit and the tasks themselves. Things like scripts in `package.json` or jobs in your CircleCI config can be automatically managed and kept consistent by hooks. - -For example, the `test:local` hook in the `npm` plugin ensures the `test` script is defined in `package.json` to run `dotcom-tool-kit test:local`, then any tasks that are configured to run on `test:local` will be run when you run `npm run test`. - -Plugins can set a default hook for their tasks to run on; for example, the `JestLocal` task [runs by default on the `test:local` hook](./plugins/jest/.toolkitrc.yml#L2). If you've got multiple tasks trying to run on the same hook by default, you'll need to [configure which you want to run](./docs/resolving-hook-conflicts.md). - - - -Hooks are there to be **installed** in your repository. Hook classes contain an `install` method that updates the relevant configuration files to run that hook. This `install` method is called when you run `npx dotcom-tool-kit --install`. This lets Tool Kit plugins automatically manage files like `package.json` or `.circleci/config.yml`. Any changes made by hook installation should be committed. - -When Tool Kit starts up, it checks whether the hooks in your plugins are correctly installed, and will print an error if they're not. This prevents repos from getting out of sync with what Tool Kit expects, ensuring repos are fully consistent and controlled by Tool Kit plugins. - -### Configuration - -The `.toolkitrc.yml` file in your repo determines everything about how Tool Kit runs in that repo. It controls what plugins are included (which determine what hooks and tasks are available), gives you fine-grained control over what tasks are running on what hooks, and lets you provide options to plugins. +The `.toolkitrc.yml` file in your repo determines everything about how Tool Kit runs in that repo. It controls what plugins are included (which determine what hooks and tasks are available), gives you fine-grained control over what tasks are running on what commands, and lets you provide options to plugins, tasks, and hooks. An example `.toolkitrc.yml` might look like: @@ -122,39 +89,43 @@ An example `.toolkitrc.yml` might look like: plugins: # provides the test:local hooks - '@dotcom-tool-kit/npm' - # provides the JestLocal task + # provides the Jest task - '@dotcom-tool-kit/jest' # provides the Eslint task - '@dotcom-tool-kit/eslint' -hooks: +commands: # run both Jest and ESlint when running `npm run test` # required to resolve the conflict between their defaults test:local: - Eslint - - JestLocal + - Jest + # options for tasks can be set on a per-command basis + test:e2e: + - Jest + configFile: jest.e2e.config.js options: # ESlint plugin needs to know which files to run ESlint on. # there's a default setting, but your repo might need something else - '@dotcom-tool-kit/eslint': - files: - - server/**/*.js + tasks: + Eslint + files: + - server/**/*.js + # instruct the hook that manages your repo's `package.json` to + # install a command to run `test:e2e` as an npm script + hooks: + - PackageJson: + scripts: + test-e2e: 'test:e2e' ``` The options available for each plugin are documented in their readmes. If the tooling that a plugin is using has its own method of configuration (like `.eslintrc`, `.babelrc`, `jest.config.js`, `webpack.config.js`), Tool Kit options aren't used for that; they're not merged with that config and don't replace it. Tool Kit options are only for things that need to be known to run the tooling in the first place, or where tooling doesn't provide its own configuration. -## Contributing - -Tool Kit is organised as a monorepo with all the different plugins and libraries stored in a single repository. This allows us to quickly investigate and make changes across the whole codebase, as well as making installation easier by sharing dependencies. See the [developer documentation](./docs/developing-tool-kit.md) for a full explanation of the internal architecture of Tool Kit. - -Release versions are not kept in sync between the packages, as we do not want to have to a major version bump for every package whenever we release a breaking change for a single package. - -We use [release-please](https://github.com/googleapis/release-please) to manage releases and versioning. Every time we make a merge to main, release-please checks which packages have been changed, and creates a PR to make new releases for them. It uses the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard to determine whether updates require a patch, minor, or major version bump, and we use [commitlint](https://commitlint.js.org) to enforce the standard in all of our commits. - -This means you should make an effort to think carefully about whether the changes you're making are a new feature or bug fix, and whether they contain any breaking changes. This might seem burdensome at first but it's good practice to make sure you can predict whether other teams' builds are going to break because of your code changes! If your commit will only affect a single package then please also include the name of the package (without the `@dotcom-tool-kit` namespace) in the scope of your commit message, as this makes it easier to see where changes are being made just by a quick glance at the git log. For example, a commit message for a new feature for the `circleci` plugin might look like: -``` -feat(circleci): add support for nightly workflows -``` +## More documentation -Note that new plugins should be created with a version number of `0.1.0`. This indicates that the package is still in the early stages of development and could be subject to many breaking changes before it's stabilised. Committing breaking changes whilst your package is `<1.0.0` are treated as minor bumps (`0.2.0`) and both new features and bug fixes as patch bumps (`0.1.1`.) When you're ready, you can release a 1.0 of your plugin by including `Release-As: 1.0.0` in the body of the release commit. +- [Tool Kit's core concepts](./docs/concepts.md) +- [Extending Tool Kit with new tooling](./docs/extending-tool-kit.md) +- [How to resolve conflicts between plugins](./docs/resolving-plugin-conflicts.md) +- [Developing Tool Kit](./docs/developing-tool-kit.md) +- [Principles to follow for Tool Kit](./docs/tool-kit-principles.md) From 0d5eec0e377c8ae0b5571f751bc3728e9a6dce77 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Mon, 29 Apr 2024 16:14:42 +0100 Subject: [PATCH 269/321] docs: update concepts doc and diagrams --- docs/concepts.md | 68 +++++++++++----------------------------- etc/concepts.sketch | Bin 569815 -> 1043365 bytes etc/installing-hook.svg | 28 ++++++++--------- etc/plugin.svg | 42 ++++++++++++++----------- etc/running-command.svg | 35 +++++++++++++++++++++ etc/running-hook.svg | 37 ---------------------- 6 files changed, 90 insertions(+), 120 deletions(-) create mode 100644 etc/running-command.svg delete mode 100644 etc/running-hook.svg diff --git a/docs/concepts.md b/docs/concepts.md index f21dd49de..c359e7846 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -1,71 +1,41 @@ -## How Tool Kit works +# Tool Kit's core concepts -### Plugins +## Plugins - + Tool Kit is a fully modular set of developer tooling. Not every project requires the same tooling, so to make sure different projects only have to install and configure what they need, Tool Kit is made up of several **plugins** that you can install separately to provide different groups of functionality, like [the `npm` plugin](plugins/npm), which lets Tool Kit manage things like `package.json` scripts. -This means a project that uses Jest for its tests can install [the `jest` plugin](plugins/jest), and a project using Mocha can install [the `mocha` plugin](plugins/mocha), and be able to run them consistently anywhere they're needed, e.g. the `npm run test` script, without having to configure that manually. Plugins can depend on other plugins, so we also publish plugins like [`frontend-app`](./plugins/frontend-app/) that bundle up most of the tooling you'll need into a single package. +This means a project that uses Jest for its tests can install [the `jest` plugin](../plugins/jest), and a project using Mocha can install [the `mocha` plugin](plugins/mocha), and be able to run them consistently anywhere they're needed, e.g. the `npm run test` script, without having to configure that manually. Plugins can depend on other plugins, so we also publish plugins like [`frontend-app`](../plugins/frontend-app/) that bundle up most of the tooling you'll need for a particular use case  into a single package. -And if there's something you want to use in your repo that's not yet supported by Tool Kit, you can write a [custom plugin](docs/custom-plugins.md) so it can work consistently with any officially-supported tooling. +And if there's something you want to use in your repo that's not yet supported by Tool Kit, you can [extend it](./extending-tool-kit.md) by writing a custom plugin that works consistently with any officially-supported tooling. -Plugins provide **tasks**, which provide the code for running external tooling, and **hooks**, which manage configuration files in your repo that will be running tooling. +Plugins provide **tasks**, which provide the code for running external tooling, and **hooks**, which manage configuration files in your repo that will be running tooling. They can also configure default **commands** that will run tasks. -### Tasks +## Commands -A **task** is a lightweight abstraction for running some tooling from outside of Tool Kit. Tasks are written in TypeScript, so we can make use of modern Javascript-based tooling and libraries, easily provide structured logging and actionable error messages, and debug them more easily than things like Bash scripts. + -An example of a task is `JestLocal` from the `jest` plugin, which abstracts running Jest tests in a local development environment. Some tasks support [configuration](#configuration). This doesn't replace any native configuration that tooling might have (like a `jest.config.js`). +**Commands** are labels (like `test:local`) that you provide on the command line when running `dotcom-tool-kit`. They're assigned by `.toolkitrc.yml` files in your repo and in plugins to run [tasks](#tasks). -### Hooks +Plugins can set a default command for their tasks to run on; for example, the `Jest` task [runs by default on the `test:local` command](./plugins/jest/.toolkitrc.yml#L5). If you've got multiple tasks trying to run on the same command by default, you'll need to [configure which you want to run](./docs/resolving-plugin-conflicts.md). - +## Tasks -## How Tool Kit works +A **task** is a lightweight abstraction for running some tooling from outside of Tool Kit. Although most tasks simply make a single call to a third-party library or CLI tool, some are more complex, orchestrating the logic for things like our deployment process for Heroku. -### Plugins +Tasks are written in TypeScript, so we can make use of modern Javascript-based tooling and libraries, easily provide structured logging and actionable error messages, and debug and maintain them more easily than things like Bash scripts. - +An example of a task is `Jest` from the [`jest` plugin](../plugins/jest), which abstracts running Jest tests in a local development environment. Some tasks support [configuration](../readme.md#configuring-tool-kit). This doesn't replace any native configuration that tooling might have (like a `jest.config.js`). -Tool Kit is a fully modular set of developer tooling. Not every project requires the same tooling, so to make sure different projects only have to install and configure what they need, Tool Kit is made up of several **plugins** that you can install separately to provide different groups of functionality, like [the `npm` plugin](plugins/npm), which lets Tool Kit manage things like `package.json` scripts. - -This means a project that uses Jest for its tests can install [the `jest` plugin](plugins/jest), and a project using Mocha can install [the `mocha` plugin](plugins/mocha), and be able to run them consistently anywhere they're needed, e.g. the `npm run test` script, without having to configure that manually. Plugins can depend on other plugins, so we also publish plugins like [`frontend-app`](./plugins/frontend-app/) that bundle up most of the tooling you'll need into a single package. - -And if there's something you want to use in your repo that's not yet supported by Tool Kit, you can write a [custom plugin](docs/custom-plugins.md) so it can work consistently with any officially-supported tooling. - -Plugins provide **tasks**, which provide the code for running external tooling, and **hooks**, which manage configuration files in your repo that will be running tooling. - -### Tasks - -A **task** is a lightweight abstraction for running some tooling from outside of Tool Kit. Tasks are written in TypeScript, so we can make use of modern Javascript-based tooling and libraries, easily provide structured logging and actionable error messages, and debug them more easily than things like Bash scripts. - -An example of a task is `JestLocal` from the `jest` plugin, which abstracts running Jest tests in a local development environment. Some tasks support [configuration](#configuration). This doesn't replace any native configuration that tooling might have (like a `jest.config.js`). - -### Hooks - - - -A **hook** is the glue between configuration in your repo that will be running Tool Kit and the tasks themselves. Things like scripts in `package.json` or jobs in your CircleCI config can be automatically managed and kept consistent by hooks. - -For example, the `test:local` hook in the `npm` plugin ensures the `test` script is defined in `package.json` to run `dotcom-tool-kit test:local`, then any tasks that are configured to run on `test:local` will be run when you run `npm run test`. - -Plugins can set a default hook for their tasks to run on; for example, the `JestLocal` task [runs by default on the `test:local` hook](./plugins/jest/.toolkitrc.yml#L2). If you've got multiple tasks trying to run on the same hook by default, you'll need to [configure which you want to run](./docs/resolving-hook-conflicts.md). - - - -Hooks are there to be **installed** in your repository. Hook classes contain an `install` method that updates the relevant configuration files to run that hook. This `install` method is called when you run `npx dotcom-tool-kit --install`. This lets Tool Kit plugins automatically manage files like `package.json` or `.circleci/config.yml`. Any changes made by hook installation should be committed. - -When Tool Kit starts up, it checks whether the hooks in your plugins are correctly installed, and will print an error if they're not. This prevents repos from getting out of sync with what Tool Kit expects, ensuring repos are fully consistent and controlled by Tool Kit plugins. - -A **hook** is the glue between configuration in your repo that will be running Tool Kit and the tasks themselves. Things like scripts in `package.json` or jobs in your CircleCI config can be automatically managed and kept consistent by hooks. +## Hooks -For example, the `test:local` hook in the `npm` plugin ensures the `test` script is defined in `package.json` to run `dotcom-tool-kit test:local`, then any tasks that are configured to run on `test:local` will be run when you run `npm run test`. +A **hook** manages configuration in your repo that will be running Tool Kit commands. Things like scripts in `package.json` or jobs in your CircleCI config can be automatically managed and kept consistent by hooks. -Plugins can set a default hook for their tasks to run on; for example, the `JestLocal` task [runs by default on the `test:local` hook](./plugins/jest/.toolkitrc.yml#L2). If you've got multiple tasks trying to run on the same hook by default, you'll need to [configure which you want to run](./docs/resolving-hook-conflicts.md). +For example, `package-json-hook` plugin provides a `PackageJson` hook that lets other plugins define npm scripts and other configuration. It's used by the `npm` plugin to configure things like the `test` script to run `dotcom-tool-kit test:local`. Any tasks that are configured to run on `test:local` will then be run when you run `npm run test`. - + Hooks are there to be **installed** in your repository. Hook classes contain an `install` method that updates the relevant configuration files to run that hook. This `install` method is called when you run `npx dotcom-tool-kit --install`. This lets Tool Kit plugins automatically manage files like `package.json` or `.circleci/config.yml`. Any changes made by hook installation should be committed. -When Tool Kit starts up, it checks whether the hooks in your plugins are correctly installed, and will print an error if they're not. This prevents repos from getting out of sync with what Tool Kit expects, ensuring repos are fully consistent and controlled by Tool Kit plugins. +When Tool Kit starts up, it checks whether the hooks in your plugins are correctly installed, and will print an error if they're not. This prevents repos from getting out of sync with what Tool Kit expects, ensuring repos are fully consistent and correctly managed by plugins. diff --git a/etc/concepts.sketch b/etc/concepts.sketch index 20de6f6f969b97828d2b2d249e9eb26dc66d7c2c..ca1e9b41f6ccf097134ae136caba8693d9d81eb9 100644 GIT binary patch literal 1043365 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

JzzF-$MPl_M5pDGy{1)Gmv|Xhs-jtzhGv; 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

y)_gbXw0z@v(o;_isS^w)c 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ℜo`BZaT^SS0Tpf`&(_i%c^mzu9MUjxaxulbqt0$$Tr^9$##dCj%g z{K|FE5DuqlaK0KDyhRz;N%I@mP4kxPtSRTZYJTUs1Ig(E!KA0=53UDi$Mxnot{2dr zzMPip0}RU_SXO^vTK#}%4M2NZ#0e;212+ihRsc7cs|Doh9Uxam;8(S|;Xs-`0xA>; z%qtkkR}fd18v*2NB#@&JU|^xZp_XtBxzU_6Hu(nsG5)6VA#t<|42cb~NY4MRM*y$XZ}m>{d8!;S}e|<#TOt?#pRlS1&mq%`2`Q zP_|K=g`23Eu9*kEFAqrKT-5eCz}(`1y~P4~iwE+y0-eiz41Eqt7nzQ(F$tXv+fP`z zFmt9#^M9!s*z(2>dsuO`sm{-T{IB1-S7I3Qdnfr~}fvfi$fEBlbX%4Cg{Ys#t6#pUutZ-bX`R#T8()_x;>4 z?j(1fyTX0WeU0k>3rD!$a1>`PySjGHcJ6kq?7Zzd;#khXc0qQd>?YV*?UL-$?WWt! zvRi1k%5Ib0HoFqLBX%e3&e>hDyJdIV?kl_R>|WaauC><++Im_it&6s))?3?N+gUq6 zJ5)PbJ5d{@P1a^=bF~Y!E3~V%h1%`fVr{ARjP|njy7n{eR}clBYv0&w?M3_g_O3Ye zv#Wi7`{DNE?Gx;$+RwMox8Gu4Y+q`B#{RbbclJbAL-&rZp3b84(D~@P=?3b?=wftJ zb#rtJbt`n6b-Q(kbf>WS`RBTS>7MB*Z^zf*YvV{zGw;qf=Y4oTzB}*F5934lv3w*S z$0zfdd@etq|B%n;*Yi90J^T^=41bfq%YVZ^;a~Dpuhk3sx_TFVD}85uKYg%%ygph# zSwCGrSHD=F@0pkuAKx=P*_v+cnGhC{oRruzDLN_98rL%!Tv%8{TB@~YU**wT{f!8N zo8A$z$q{J@QSsKy-jPYEVG-ckQu`=YeGo=iYF{P9zKTiTN*8_A82YL)^jF;UuL`Pv zL{dURm>O9BN>2mA!;%M7Ir3M0`Bz%|t6}=9Vfv@W#z$KH2M(W_eG{XHDsc{tNdrZa(-Pvt(o%=2(GE?C4@-$rdj0x=>ozBt729)hG@l2bX8E%)hH5O=_v-ZiK%iFtN4obgng_UT&x;g ztU`;}Nok3(ZM}UuOset{S1sJQ=wz!kkqI-g5fIK$zvGoe##eI_kFXOJyF|q}K~nXiNm5giR8<{tCYk6cuV+|%>YohM4^*pgYkX1$N;=$DuFR!UIxH(nxv`h3qEo(Dm&;z1(q%7d z$+I`5TCkVO=AwMq8a{hx^@2UCR~`1P&Z6bP=o>X5Dyu3*SxR!J zDrucs8S7MQa*}6!D%v)FQ#06mY7AN$o>56@$?OrE&c0G&Gubc3n?yXVN)gAWCdMir zBa_fYGRLeEGG`!uJWGFkYL?k993^n92;@d%6#C z)OZ2oEqEO`3KI?(AH`4Lv-vsvyZmw-GQO4nf`6sg=|z2g953EaKS)1J9|~S!p?-<} zkp7#z_9isw75cG&E&!{MMqslzE8Do$$XYZzw5zx$uqfLiod=Hy8}H4Nis@hK`2Lh5?2Vh6qEn zA>NQ|n1KUbmKatU3JtpqM+|2SpBQc$?irpKUK)O@X;-sW%?34HYqqS}I*kk>8}y`J z$4{tR|A6ewa5HVHU$^_%vVG21wx&+8(1!LoGpEi>b52WJR#;ew|1~pnmRbzNozyu; z+@A$qqQ>18pN+coMLCPtI<4Qjc+ZW?>DF^*(nG&FG;nQOXKJCEKD563sbJy|Z}~n& zS1@PA+)Ss$@c9w_yKLJTij#ydjVTTc91}fw@UiH#XO9(M!b#2!{Ptqq<{j&{?sYmd zVdt2T$k?&g!sJc4aQ&~VC*N3TT|Rl{jH%ORuGnOzCf@aG$iLWO%}sx5OWaELFI~UG zOj_x)lagn~I**Fnc;?K$jmLLwnwh=T0^{}Z;Y)E0wp;VIv?+38;7{JuZ7g25?|{>% zqxJ<285cG@v^Z|>EVE%`OWk|=eT(+bjCab)&P|MsS-B~}?5fY&vODKv=dUgw{`x>l zaYUizI%%Z)fadEBWA;TJJ65vq*s+L`F=HYl#vnzm{17@JfK1TQ;XG+mj^m(P@u!LZ z8S2m8NE>;yjt=Al=meZSj>FBvNhiAT3VENjqwk+18;Ktdd45179Ua2^CQF7%`VE<} z>yh@_ecDoyinrR5+NHbJZ&+s`4eYaLWlm3Vj!NBj5XUByMm(uOqyiy2Dtb==PV#<0 zymYkBLBX(PZC2uk7I%K@k~QnLIva^=%V)F+b!*{4U8(Dj9>mQsyfpdb_VtUGtuw#S z&zv@UUas?u*&i)4kP_P3M5f8FbaW{1PviQLI32|q-JQ#O^{0JtK5HTAV|q#Z=twM2 zMG~gFva95iZ=FbEkFTk-nSP8T*n>zP9;YXpCZ!Z?-L`RkQPIYX#H5t;Nfz-g`M^Fd ztzgU6!h)SU3)7P(r=`bP#7E^W_Bia7yGHnH*3ysyxI4CGLn)5YuGRPo6{yg7AgwiG z!{}p^&EnILbnEB=PU0iV6K();G8_F&q~&v7eEN99)w3_1o`jsIHFlXhY|v$Vn6r3| z)4DB-i?3YFh(2v59rfakNvmV>$1iqxOk1|qi%(mo4;a+cspZEZ#4f@7I8C=6bvDZ> zDRO?~z#dz7j51T^Wq0POtn;%Sj3nN4oTn~3UbQDpozEW5->}OvX8mm5Ia6U(3v)A;!7LFSwg$*&*Z0v z>y4doM(~!ox()M|%*%C}F=JjzSeJsG6VW~{=9wA`h9MFOF*Ln2=*JU>*KOToHn1Fj z%Wqn=Vab~14yftkjqIdJ)tZ1sytu2#)(WOBPhFDyp~ExUQZH_6q8InHN*vOO@=oG5 zs=wIzhXk{+iDdl$_9%5vo_Lb8ILF+ZHYIKJv=cq6nG=K2^Gtym0tvszqQ+45evnP&n!dbnI-ZUjH=1)nU zDIz{0+#0vNq-5ugz592>N8niXgXtTmtTu06U9j<>(=X}~>7SC;)RpfZ64K2=8|amD z)FWuC65AQ+4fNekhJ0=&uB3Hu^&oX4$uXVf-;J4_o}1wiMZM)z{HYJNZY*^^Sdx>4UZ%T#O=8H(;pk;NJJ5QTm_WVJ)DGfjh>i;S2PHb1iJ<}K zE%W8Aap3SX-teJB0u3(`bKZuakBb*@cGCH~In7 z69Xs2tz@ULPd@5=d+nEBqZ{jF61N?`sylLh@5MV#MBC*q6<}}h5FM4pnWpwgoIrqZUxc+>ZUVJ5z-_>o+SQEni0V?dVl2c+0p(wmW?qu(xlY0Bi4r6^UD>nGMTHhPz}SQ+AtD3l60n zb|$9lZ%BPozyBL*8b2W|H64A_Qi1$XZ>eDXxf9Ng7rs66^Vg9j)P4(WPEc2!J8u}4 zhx4U7k~Ri;o~i%o;OjTeoW6b|=uE%3Z<#{$_)IL;8fm@y^uL-<8&<^{=}U)8Rvf8wxBqBfiTM(uJK|--dR1Lc8b;bJwh& zzulP_uiPPZEe6K~6agJU?5RZjqs*k6zUTH)r-;sp=#HQIY&$cc{!tXxbcB;pe%p^_ zbE0IBM-LJV`B~x1qn!<9XH8Qi@w2Xi_(Pr`eqoSrnP?sAM{5#4S_h|k*CCxqP1*^a z0o_-=$0Uy=HOoixIQM;YhJnP26Q>C1AwoLoQlc{>!<>2_k33@*3oafxaPH&ioz^8N z>?0=fJ2mJ?V?E72N3zf8h?|}=lk#5n~e>hvy?FY3L%zMxJ!18+9a&r(rm3 zek40=KAA^?mg$fKlfks9XmP>&n;kGny*FcC&a^a#h!GRV_Hd%wFS`-($6H0krDg-2 zX8+Zdeb@G;Z%xRz7-FW)Oq@0M{rBg)Wa{1 z7H&IWG29<;t)p-M0Udp>_kVEz+Vux!!=$NO#ya=P>f&d4fn&#M;BRJ}D4sJjF9*R% zI>R8rNIT~dFVc>98E8oPTfBfcC8_|iI^;5<~%^vGKIwF5}mW6CO!5gUCZd3NG?A&zc#GG|oj%?k&bKUB^?1dKN z_I0avhGYpD#Xd!R-KtM(g9tztNHbJ*Fa@1cQ}fZ^cBEQS=?Af338b}J+US44sgJi4V6lQkn{ zl(`S7eTzT7KE-M=5?#}m7hk#)-jMgIS2`K~YU`^XUf~$^^>`e{zhO^*P|KTqigYZ_ zn7k<7*+2u!M;n&OR~t))Z%T!glLbRx$!Pku^X(SRI`?vM`>NNAAHTZ&%4{qw*d-Yh z{-G)O2YLPx!9XqPjoo?6~G9(j{rWt>N%X6IziOLaErXj`xdfxICtYi(h{ z+BJn1@mP<7HB-@HOwY;5$jHfGxhg+@{rdczY_nm`qrvG!`WM`jfg}j$%Rk~akwtj6 zmV1!a9FAA-{0ArHYW~pd%+(a4mkB8|n`k4x69yMz;tdNjNO;Cr$uLXe3<(9(1w%UN zLt3GEwr3pF4_|@oZmqtejZoz@rW-`d_^^Idt220lP}B1Rx@6eNz zFw~LO#F6wrJtFsCP5cd|WUT4zn1e$HkC_-~xOe3qM;bo3@{Ly3 z8WM8SldMjLfHDt)9{Nd{STTEJGZ_KN=3|kVsKnZV%MTKIl02{`Kxa_BUeUZFwo|M%96Q7atp1Y%sd%Y zVk8G%K1xf7;jZJV2N#k3XI~=sb1(+Y;f*HZQIz&T;_`ehKPTD)0-#PTo zg?Dbg^TRu@YwK#)uI*X7bL~O3b8A1T)38pHI?;7D);VA2lRCdUwsG7i))bw^5HUyG zBpwvMsOwy}S>1_sr`0`I_nyh$6l(h1^r)Usy#e(m)|*)`zus5%?drSM_o?5veoXzT z_1~?(vi_6$q=BhHlLoCC1UHCikk_EF!JY<(8ww2@Hf+{#a6@auoQ9hl-fZ~HsfkmB zQ;ySWr^`;SoNGI~ICpk_&v}*e%SOgVJsZU|n$zghMsFlR>L}$)yQSmOH`1@r0W+9Q zW*2iSb02ezd7inze8POg{H?{_(#O)@5^0%b`PlLd(}SH|hPgz!8^3a^9q4H#$7%@V2AS(Wzt0j_o>j z>zLc|y^e?cOny!LeEfR)4e=Z87wI?IZ@S-yek=Vp`R(>Q;&;LCGe6qN(8+k%SYFde zPt7J{Y5(*xF2ivHi5Dktc)CL{i+flPWfmt7MJHt`A~hja@cU(V9nI#Av@dy1Hee)b zTud5ki^y{mX-qcI#ysgqH&nbEpA@8{C((UFAm(Op>t(8yACk4E=KT6^bU*T2h)&mn zFD9*YROF**E1eg=hkexLqw&#f z?WA~|q<&&N>Z&DIN%2^LPLabiNMr^_>ORyyl;@lLtp|Hv*{kdR@N@kY>%q_b_g>vQ z@w0(e-RJGQ>j&-&YgnKE?A7TXSl$jmLZI%7=E338VZbKfSxqI zt}Aa#hUtw1!Pspf0foX6IhkgV3F02|FhKHTV#QhF$B_-hUt1`TFp=SWN7_sGuKv@- zH!}mBfYF8w8@B1-NHguOPdI!&?O)EM!LN6T`HuBW-x3S4Co^;l%lqn$^9#~{A#I5a zN`6B+XytB5#weanH7_&f-5KM_~Q)msI! zqMa1AQCLNK!)G5cldS52a@;GR6vccL6nWQPj2Uut?D-2vk6yeq_6RzF{9$9q4F;jV zBr{2Tq2hAlvLOPMF3R!TR`R=cYnHTRnQ%-_(jHr6GcJa)+<2@Mxvf+DDOEBTv;IWApE*(2~7D+rmX8&NA4jmIV99-~F>Ul=`@q#3NBj1-@Otd*a zH&J&;u!tY~9PR&j-@g2v8_nW3odxmZ8PWiWTTteyZ6dhQj1b8lc0JG1x@LM9Sk@(8d`;?pc9C!vQN9&+cKA9o&Aep# z@}7R@+MFp>*N4HS4|KViP4Et221l#HX%la3+24@qYjk<@zlm`!}??1y9xptmvQZ}rAp zB~0LbbF}0c>0s(M{N%sByIA_*tFvj74_Q2f!@@b>$j0{tG|>=k2Q*13kMx#DpxRD^ z!Pvm_bv+ZbuoDoGB`Pz;LdMF~dIQLzpryGWo`=D8LB0pkuJL> zx?h0@ySyuXlZW2m0_h4eg_5aAlAJXba>I9FCv>H!w|{oui3Ctb(vSw=u0z>#5ISa< zmh4@!ve^6qIc7?opFS_k9C4i5dmRbX&FA}%yY}SCku%q?9}8+@F)o!5vj=(&ABk+Y zj}(IQK9IO2B=|K6)o$8rNetS$lCi+ns*ntn7kY_gAsc|a@oQviL0Lns>|2jf zOGn4@)Ifhh_5MXiBYBbmF~CTQ6<6PC$s74?Gr@QsfkkAH?it*BW%gRR3>`%z00<8+ z;-RCHcoIZU(sA^fj#&8@#P4V7rz4YiI*we^8E+sYl7Pgu6^si|Ve;jzT6r(&)EzQ% za)+%_5$UTXQSzL%QdLh&e9O#xCB+&Q8TR#WtPxzuTe6fkAPpRs$pgd!(iVwmN|)-0 zCofL?gw)oF1)tE`>=W?ZQk{_wr2Wz9uP5JY*VFzc@;#C0_h10-%5z8!^afVR=qoG~ zo{&Leb_+o)b&-to1PD})JJt*0_&|wFqk(#H_ittrs3)83*DWc?-v|h5(u4^qlOm>M z=C7M&F{Vn~a#VuhHm?UHaUHo;j|7&PX&{}(S4VLy;`nMnj(M6e7<4&CI%{2pQsQcA zBhi?3!cpQ?DBL2$0T_N?<`f`^Pje+>h~T)K41w%9OuS7lo@pnDk4_5Wy;hR=JYF!K z5OzpUNT67{qh6sT-Xr;XZ=tV1rX%sjP+<=l3CZ@x1Ylx|Bx8yozsZ1+V*!bxW8ul0 zOgSQmi_3fH<0a9XTJ&Pz7)k81Oy1lWu0sV9pTQ*v+E~F@kj{odypt*CAnoTA92f4B zK>XEhB$mq2vX^OlqP1YC^QiHeNhucb-un_#vf-n(D+`>rEKi$kq3@$%{oUkay;%D5 zkWW1NjY&$KVm2le>=wksN>1)7IS~){6~w!Hl*}l!CL9@}g>aeSDH!KTq~$WTymkjl z;+@@q1YV)EW(%qfiem@41=t^i*(bkJiZf;u9Fk`CnX}S!Qk)}FiVhvxSX8okT~6i_ zj1&wEVDyqT@>r9&CrJ=*^by_@Cg8bd=X6QDI6@L1G!?{)9nlMoUng+)$Z##j;fvEG zdJ*G+v4<2Rh?&bJV7jaIE%DkJua~8eP&7Juv6eipM|!eJlR=n*nB0#{*3n>|^u)x9 zk@zw_Ep;mmf|+jr;F76jBpPn zy0MQ$U!bR;HRZ8d@+ekn$CvBS6Mf4YH~03nbe_q)009VrEk!osx(Iyx?al z?IY69?exTj>|zA!MhABzgLO2DM}yy`YlkN9ULx%x&$PQb3jLZ9Gr(^%_}{Md9Wr

i{{L5%AJ!pb-uaJQQg$#b3a<)wEUxGs~4Inch@vBEk0s|(~#mx z*CPN+zaFAnI(N~WSxz}KW~Gh`S-X9lnY!zfj(wbS)0ybLKJ{Hm_SQ7a`P@FSVQ0xH zr;E`={Y%V^FY0D4n)}fbr~DO5HXJ#bm2kvN-1S?>gy#2kraHe7Z82*UzG`won%PKy zv`H$hR57I$#FSRN(bLv_0UfbQ7-@jCPyRdHx~B?mHFiF=MIh@>nMOX{DoVb&*#K;xN7NmRZC4olEfqt%Ymk!Xg9)> zZa?wp$nBf!#feWSuNMp2G}jwxGsW0*~FI7DLcr)6B}vU*;E@?(_8ERZ$=$`t!)p4NND+r&6= z$4Q$c_nQS`oan5nkl>g^XNEPC>MZghMU)c@+RDA_B}#7f5(PN@Z8^EON-#DDBSPkr zv8dEmjN^&o15!lNCQ18+o$J@`*l!VU9Fm3|3%_*X*nx9q<1q=vuu?16mh*Z_6<_3- zoVQ0(P&?{C92_5z`zV=PWoAD?oVa~I#@1-b7$8pvV`QGlIta7l4=;$_3$YJ52T)R+ zjR}M1Ns`zgf9bM(v)HF-%^>DJkJRCao)l_{Ue24zOfrcN_bdaf;6gdGDuyjm1B70~_ za3HfANP;=yL%M58`ZAL>Ix#NX$xB+fV#%@N7Gx6n(aJt$=JqJ1LbZODEoSxeqCkFK zC3PcS*`(b$;^&CYAxJ#DPZCESeWW8JdGWBfJYm!SCA|${A8Ki#( zSHig4A@(J!bab3N9`o#L-soTLXHzI{;W~gIA#{U2Vw%qQWP~t4APva4kpelfO1h%t z3bi;0RU}ATb|+RUf1jsgXbtE9GXWJ(GR7jmKSSWlXVPL*`_ZQ#ep`C_q2*&*jGi+d z!miz~gyR;I1~*9qE%{y!Gd&-0wORB2{w-Tx_y6g|wX4s~v_ZYNob_L(d{V zEzWFQ&DfTnq?~jX6Xg|oInrE7Oiz%+#7T$FX5DlacaIT5g$>{WKLT^93iKDipOb|Q z)M&o4oJ% zv~$j3!llfUvHLBvC8#2_{YaQAkWqQWow}1Yd%xcaWY~qcqzSSkQkG5@$&se&`U9s+ z*KXTuN!))r>!Pzdks=QAB+OqXlGNv5@8;7Eq~)#yDvP%Rou?=u#|rD&6wJTbYA}sY4>T&xlubT-;e~|hxF?Y^tliK^a~~G=--Ws=(ld7 zuX{#nXi2R6cCmC?-g=+=;k#cSks6P*>*cMcJGA?Er2FUh>0Dm+qtT{ww{_Iv5n1f3 z4`?^|Tb(am{0Isw=OFNWvP!y5+^;|uKfYO7MrN5x=&XSPof^TDsWj1a`zCSkdnFz0 z->?O*0lV{LVFvdK1&~KpXyupVrH%62zLMOTwpcfFk;4~DGtLWSFc~Ng+dC9+26^z9*gxh<9>004CH3TF z(~gaswr$&(93P*OoS2xh37R$|>)ji8rEAxL13PuPGVqHpu3WiiW~^nq9TE}{C>E=t zz;B1ZS&E;}7D#}S!skB{-`9?i26^)FFJOVo$4k^-{>Vghd^1V@l`c_|n_ZdQQkL9o zmfTWXa*cEeS)$MpoYD#{v66CyZnP~~zT@nhqLZh0aD_!TKPkC(||W`swStZ_JbGdHVe%!uh>dNe8ISt?C#S0(Infd-~XX@14yF&MdGXM0eu|xBKWlumg{~N#zqhFwt7~x{x}1iot8XZhS0;&TM?I+~1U6Y@V`LjHB0K)aOpMEn!kXjn-6$!0PDb7djoWCfIg z?!*1^^uba;q4X$(wcpA-JS5t9G>{n8L_uY!7t1P4ijYZ6%2GGv^Yy*5G?vM?N+#*M z^qopiGGFG=Q=lF!7<#4%-WU!ur_5uHRP~uywjW`>FEGLlBmUkb#GCkwPdh;Lr27!` zsFH}|&~rMzzvTGw@cpAK;?JWZ!tr>D_*A<`Rd!DmyK0dwWGP^X3?ohv89LwvsrO<4 z87lrDi{TQ~5ytxnA4#$|%dgym$}WPji!fHsLy~3+07^lk&>jb+o+MQKfjFr-eXZnF zyhToz_kw$P@62L>nhNtiQ`mv1;B6#}Y83M*H$YVGt!d9mTZMQTgeFbgOWQLA-)7(T0xp0s_e7)*lu&j`44R3O z^E@RoG%`h+CAq!AhUl%jH}a z;d{9(#>=^_0JG)Fo$bX9xybFixu|b*a@7nj&Q&t_9;;M9nzqSCCa2If8qrHu*)N#8;7R1l5q`9Tw^2p_1=JmhXen(oL|ofpj$wASxX|)WOSA z4~Z52b`nS>WE{|@n03Fh_|vM2I7=Zl zjX;|ybz&XHT?LdPi^`n#NH(<@mXZe$_-=S3i_^=(Se=*E-r!wfAJj(__)22LAQt)p zAlAs^(t47iUGFO`DQ43)V*arXLd6WuaDj@O0eJqd-4i8MyvlA?fo>)rFlLQ|Iu@^8 zTfw6l3sMC(@8rl3avDSe(7J=@0+aaEO#+%Bn8crx1v)-eAQwqf1?c+{wr)V3&P*XY3YKi92nsMEfhytn8tuI{wA9Y zgvpDt08-Z{u`Uokz^Vl2M^ zUgJFRQFx7M849N({@Qe36UZv-Y#a{6_u=FKCYk8Fr6zI!QxylGz*X)J>z8!ktDi;- zoIHyO-Pu6nvjNx@N;@Gp$MZYAb@zBhaSCF1{<6gf4_Ih6rW@4BssU2*C#OGIO|;;Y z?p?hnJ^`Ea$Fg5nOX8EvV(Gi`At93Z$2W44X(NP<>hgIhkyH`A6e9Xqn}}XoA)?d3 z{gOY8G>KzXDSZ~IkyJHdC3_QjjxWXj3OP0#nL$%l=ckf7%L^Q_)_=}uW4 za75eC7D#u}b1!N2oyy4`!W5a7%mE|%E^ChEZqgyBX;egG5#Lr!42tC}CR-8h!IVZl z_$rsj3>Bz-`2)p=Mf{<1D$(qLvGuS(YGM*^0CE3PK?I^4k3+*0J%D&`ncUn|Qr;Y& z14t+xKtkl^CA|2YxJR54Xy_>+LQisNs!6=}B?;}KH=Yw9PecneRpF)I7g$S5A*S9W zqz_2M_}Sc96RPGk;|zWht; zfd`fK4H54m?5A<6mhN2$1yA#UYUwa1N}Eh#%y9?=@(?i-t`46V2#(!0UCP9tiWyV# zT7ClJUqBc5HiLP|Rr)`xt^X5$jxH;%m`G**SUSlx#?a3A&BKH_Rm`zsI<>Q6A$!X~ z;{`gSJV>!&1?o>aVG5Q7JWL6=ePzG^>ilg1yn!ljQ)Qm^2vqpkRIMCB=K~D9U4*4V zTDi5t%-0_6BY^L}f>gi|@DO8AC((g0tw{aQ4@tlh$O5lP0*mLl8)#1+loi7XP#3>- zpvo@HE0KNF!!&#I*106s152y_xG$KQagf#G+e6BRrTjVnRNf9?NIVlH8Gg0^JFu5Ut9KgIMSg8JJiLd3+ zF(-7OVy`f&?TZ&#y6HqafHw+Jz+9CZ)yKuFAAD zfQ~i~nEpz|%rx=$?M&NzMXjj0)~`sL&JR$3{K`-A6_ePkt5sZ+R95<)^o25;%~~8p zsR0?%0Ekl0$wj3+UjF7`uSi@|%i0G?*-A5mE8vAAw4`I4K$`rvj|omE(cG>t7gz{~ zNcV7rAhUHT3;D@OnMsovc)VfvCjif1-#K>h)~`;aoQ|N+^!;KYLqlWs-7u49_%7Fr z@&(MRD?&d4N`Tm(fRMiMV_kWTvJW7JWGn5KrJ&V|t}LB$4YlchiKhD;^1R<~*G%G< zqzBRbK)PD~T|Cb(2vY@lIcpM|Mq^5Ts-Vuz&r!M`SgmJL;A&>YX73fTF9%}%&m>2c zc4bA_!>kuvR7r{B6z^5v(*b2Lfe-_2wW)gAgUR|Z#^A#Nkcq-x5<>;zUH-KqCaxzw z3x&2B5){k^iK$G=+s_2CX_`dxu&W|1)>$a@A%(86PJr!kCIX^m{(vcgUdq_Sd8BVk zCp~|~jHDt{((XhMuWKOa)i?dq3cl-T$!jEWO>Wf+FN?Tdqc9rg|F|S@mOe~kQlmvI z)>KN4W^t`1O%I82waS((6o!E<>4xNvKS_vueYMo7-bP6bJb9^D5>s4AU9>Ybn93k5 zVu=e>2v(z)@Tvs9qvcqIQ%^2mkRypnK)^GAfJfU9@ZvE-DwA9wT<#%XGKUb&Ep(l` z1jPcIx!i*Bzc4>uWv)s(m~uF&aQpd;+usI}@@aWJo1?X4WSY<$9KsCM|K6deNWMiqMOFkFfdl1>^eYZCQn_!GwI6}!LDhPfb!LLj_W!J`#i5kNERVM$>rVF|fU4xuuf5Z0;Xyh#w(%tSGllxI}a9}(AFy`>k6NUc74ag9>aMdKp$ z@TIIdI7lRTJE-Vs+)?y2Y#Jxx3CtI@!T(O;^^w^1SQ0kS{Qs{wyIy!YY$G8w83bV|`6`^&;CMR#^%+8x(7B45x-V*LSC>yJGp7P@P z{Kd;wn8k-%mrUO8{K+aTLK81X(vd0BuoQvxvBmkZO;4s%E=0R-xtI!Hl}qMQJ;dJf z9(=qccFJWk-RRsglGt5iQ=4H*Hjsi90HzZF7+(g!tf~NDs=O*bAq}R0jTxOm;<1z? z6wHzwE0ot_qvz|tE+a-otXxTKVd^^;h1c6aRm3*!$0^LJE&y|1@SOLM|3UYO`31!fM5i)d)L{{kG zrn91X)SrPu=z7wGW*Jg*pfa~qogwjgFj>}B0+=)-P#~HA3?u(`rYiIgZq!bedi z@h}vO?)HJ1Y|kk3w91GMQpoYK1gwUs2nLF`H`vO8l$6ymiMQeP5z|dVQW$7NjM5CZmZN4r3HOrbwVllYuHlc0_Lq(Ni8QDIu|*363_AT}q#{l=VrQ&?o(- zg!?UgJ%z6gO#7+1!u1g)T*rJe%$EeP9_K0H)Y5B8VynSdj}(O|R30Z%?~n~nQT3)K zgwc8j&}xShr^BS)cr)v?e6-(drB36j9)o)Di zN)Hr_^*0RH;=qP*pjYg208*+F7Q?0v;C}x#IL7>OjJP{Jy z8!RI_Nia*YBU5t_i*m_$>RJh`#pfcZqFe^8ovs2_ksfOjB}K_BP^pA1BB5zUd}l$g1xg>V5TDAul%l`OivB5zUZXm( zc~f-LCX=~9KM54p7=%X#0K@y43{de?6~GhkmQp(eO;4ed@grjkF$EJZ-q;|oRh7Y@ zFQzQc*d{d3gVJ-Sbh$TkRH45z68bBjO_Id?{lHE~DoQM7G58SR)JUesf_J9M!Zda; zJy@x-a|kLsm$8zrLJjC3)PSJdKdDl;f6_(FxlFCpO`3X1fG&vgt>}VGy@;g;YsMSv;T^1wRWYe0&x0eJ+JxmKzJF{lLJ=Othx0cFmZvAYQA<>W|`70ZAfgUdXEu=IS+kA2d~;@1RvY0w&w&EPn)D-{yRqW9RWyja={ zm3DE3)24)<3*Aw<(7xiDlm7r3q{TUOd=MAla_!JU-OmHc2NRLeD|bMu>P%60CW$$kBg|^R)yS{Ra7o{kX%

LYAk5|QB!P`kk4kEi+V?m(|9$n3|@;# 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